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