using Application.Abstractions.Cache;
using Application.Abstractions.YouTube;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
namespace Infrastructure.YouTube;
///
/// PubSubHubbub 구독 자동 갱신 BackgroundService
/// 구독은 약 10일 후 만료 → 7일마다 재구독
///
internal sealed class YouTubePubSubRenewalService(
IYouTubePubSubService pubSubService,
IConnectionMultiplexer redis,
ILogger logger
) : BackgroundService
{
private static readonly TimeSpan RenewalInterval = TimeSpan.FromDays(7);
private static readonly TimeSpan InitialDelay = TimeSpan.FromSeconds(30);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Delay(InitialDelay, stoppingToken);
logger.LogInformation("[PubSub Renewal] 서비스 시작 — 갱신 주기: {Interval}일", RenewalInterval.TotalDays);
while (!stoppingToken.IsCancellationRequested)
{
try
{
await RenewAllSubscriptionsAsync(stoppingToken);
}
catch (Exception ex)
{
logger.LogError(ex, "[PubSub Renewal] 구독 갱신 중 오류");
}
await Task.Delay(RenewalInterval, stoppingToken);
}
}
private async Task RenewAllSubscriptionsAsync(CancellationToken ct)
{
var db = redis.GetDatabase();
var channelIds = await db.SetMembersAsync(CacheKeys.YouTubePubSubChannels);
if (channelIds.Length == 0)
{
logger.LogInformation("[PubSub Renewal] 구독 중인 채널 없음");
return;
}
var renewed = 0;
foreach (var channelId in channelIds)
{
var id = channelId.ToString();
var success = await pubSubService.SubscribeAsync(id, ct);
if (success)
{
renewed++;
}
// 요청 간 1초 간격
await Task.Delay(TimeSpan.FromSeconds(1), ct);
}
logger.LogInformation("[PubSub Renewal] {Renewed}/{Total} 채널 구독 갱신 완료", renewed, channelIds.Length);
}
}