YouTubePubSubRenewalService.cs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. using Application.Abstractions.Cache;
  2. using Application.Abstractions.YouTube;
  3. using Microsoft.Extensions.Hosting;
  4. using Microsoft.Extensions.Logging;
  5. using StackExchange.Redis;
  6. namespace Infrastructure.YouTube;
  7. /// <summary>
  8. /// PubSubHubbub 구독 자동 갱신 BackgroundService
  9. /// 구독은 약 10일 후 만료 → 7일마다 재구독
  10. /// </summary>
  11. internal sealed class YouTubePubSubRenewalService(
  12. IYouTubePubSubService pubSubService,
  13. IConnectionMultiplexer redis,
  14. ILogger<YouTubePubSubRenewalService> logger
  15. ) : BackgroundService
  16. {
  17. private static readonly TimeSpan RenewalInterval = TimeSpan.FromDays(7);
  18. private static readonly TimeSpan InitialDelay = TimeSpan.FromSeconds(30);
  19. protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  20. {
  21. await Task.Delay(InitialDelay, stoppingToken);
  22. logger.LogInformation("[PubSub Renewal] 서비스 시작 — 갱신 주기: {Interval}일", RenewalInterval.TotalDays);
  23. while (!stoppingToken.IsCancellationRequested)
  24. {
  25. try
  26. {
  27. await RenewAllSubscriptionsAsync(stoppingToken);
  28. }
  29. catch (Exception ex)
  30. {
  31. logger.LogError(ex, "[PubSub Renewal] 구독 갱신 중 오류");
  32. }
  33. await Task.Delay(RenewalInterval, stoppingToken);
  34. }
  35. }
  36. private async Task RenewAllSubscriptionsAsync(CancellationToken ct)
  37. {
  38. var db = redis.GetDatabase();
  39. var channelIds = await db.SetMembersAsync(CacheKeys.YouTubePubSubChannels);
  40. if (channelIds.Length == 0)
  41. {
  42. logger.LogInformation("[PubSub Renewal] 구독 중인 채널 없음");
  43. return;
  44. }
  45. var renewed = 0;
  46. foreach (var channelId in channelIds)
  47. {
  48. var id = channelId.ToString();
  49. var success = await pubSubService.SubscribeAsync(id, ct);
  50. if (success)
  51. {
  52. renewed++;
  53. }
  54. // 요청 간 1초 간격
  55. await Task.Delay(TimeSpan.FromSeconds(1), ct);
  56. }
  57. logger.LogInformation("[PubSub Renewal] {Renewed}/{Total} 채널 구독 갱신 완료", renewed, channelIds.Length);
  58. }
  59. }