forked from AcaMate/AcaMate_API
66 lines
2.1 KiB
C#
66 lines
2.1 KiB
C#
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<PushData> DequeueAsync(CancellationToken cancellationToken);
|
|
}
|
|
|
|
public class InMemoryPushQueue: IPushQueue
|
|
{
|
|
private readonly ConcurrentQueue<PushData> _queue = new ConcurrentQueue<PushData>();
|
|
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<PushData> DequeueAsync(CancellationToken cancellationToken)
|
|
{
|
|
await _signal.WaitAsync(cancellationToken);
|
|
_queue.TryDequeue(out var pushData);
|
|
return pushData;
|
|
}
|
|
}
|
|
|
|
public class PushBackgroundService : BackgroundService
|
|
{
|
|
private readonly IPushQueue _queue;
|
|
private readonly IServiceScopeFactory _scopeFactory;
|
|
|
|
public PushBackgroundService(IPushQueue queue, IServiceScopeFactory scopeFactory)
|
|
{
|
|
_queue = queue;
|
|
_scopeFactory = scopeFactory;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
var pushData = await _queue.DequeueAsync(stoppingToken);
|
|
|
|
using var scope = _scopeFactory.CreateScope();
|
|
var pushService = scope.ServiceProvider.GetRequiredService<IPushService>();
|
|
|
|
try
|
|
{
|
|
await pushService.SendPushNotificationAsync(pushData.pushToken, pushData.payload);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"푸시 전송 실패: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} |