using System.Collections.Concurrent; using Back.Program.Models.Entities; using Back.Program.Services.V1.Interfaces; namespace Back.Program.Services.V1 { public interface IPushQueue { void Enqueue(PushData pushData); Task DequeueAsync(CancellationToken cancellationToken); } public class InMemoryPushQueue: IPushQueue { private readonly ConcurrentQueue _queue = new ConcurrentQueue(); private readonly SemaphoreSlim _signal = new SemaphoreSlim(0); public void Enqueue(PushData pushData) { if( pushData is null ) throw new ArgumentNullException(nameof(pushData)); _queue.Enqueue(pushData); _signal.Release(); } public async Task DequeueAsync(CancellationToken cancellationToken) { await _signal.WaitAsync(cancellationToken); _queue.TryDequeue(out var pushData); return pushData; } } public class PushBackgroundService : BackgroundService { private readonly IPushQueue _queue; private readonly IPushService _pushService; public PushBackgroundService(IPushQueue queue, IPushService pushService) { _queue = queue; _pushService = pushService; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { var pushData = await _queue.DequeueAsync(stoppingToken); try { await _pushService.SendPushNotificationAsync(pushData.pushToken, pushData.payload); } catch (Exception ex) { Console.WriteLine($"푸시 전송 실패: {ex.Message}"); } } } } }