YouTubeLiveStateStore.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. using System.Text.Json;
  2. using Application.Abstractions.YouTube;
  3. using StackExchange.Redis;
  4. namespace Infrastructure.YouTube;
  5. /// <summary>
  6. /// Redis Hash 기반 라이브 상태 저장소
  7. /// Key: "youtube:live:channels" (Hash — channelId → LiveStreamInfo JSON)
  8. /// PubSub 알림이 없으면 데이터가 없음 = 라이브 아님
  9. /// </summary>
  10. internal sealed class YouTubeLiveStateStore(IConnectionMultiplexer redis) : IYouTubeLiveStateStore
  11. {
  12. private const string HashKey = "youtube:live:channels";
  13. private static readonly TimeSpan MaxLiveDuration = TimeSpan.FromHours(12); // 안전장치: 12시간 후 자동 만료
  14. public async Task SetLiveAsync(string channelId, YouTubeLiveStreamInfo liveInfo)
  15. {
  16. var db = redis.GetDatabase();
  17. var json = JsonSerializer.Serialize(liveInfo);
  18. await db.HashSetAsync(HashKey, channelId, json);
  19. // 전체 Hash에 만료 설정 (최소 12시간은 유지)
  20. var ttl = await db.KeyTimeToLiveAsync(HashKey);
  21. if (ttl is null || ttl < MaxLiveDuration)
  22. {
  23. await db.KeyExpireAsync(HashKey, MaxLiveDuration);
  24. }
  25. }
  26. public async Task ClearLiveAsync(string channelId)
  27. {
  28. var db = redis.GetDatabase();
  29. await db.HashDeleteAsync(HashKey, channelId);
  30. }
  31. public async Task<YouTubeLiveStreamInfo?> GetLiveAsync(string channelId)
  32. {
  33. var db = redis.GetDatabase();
  34. var json = await db.HashGetAsync(HashKey, channelId);
  35. if (json.IsNullOrEmpty)
  36. {
  37. return null;
  38. }
  39. return JsonSerializer.Deserialize<YouTubeLiveStreamInfo>(json.ToString());
  40. }
  41. public async Task<IReadOnlyList<YouTubeLiveStreamInfo>> GetAllLiveAsync()
  42. {
  43. var db = redis.GetDatabase();
  44. var entries = await db.HashGetAllAsync(HashKey);
  45. var result = new List<YouTubeLiveStreamInfo>();
  46. foreach (var entry in entries)
  47. {
  48. var info = JsonSerializer.Deserialize<YouTubeLiveStreamInfo>(entry.Value.ToString());
  49. if (info is not null)
  50. {
  51. result.Add(info);
  52. }
  53. }
  54. return result.AsReadOnly();
  55. }
  56. }