Files
2026-07-05 23:20:20 +03:00

62 lines
1.9 KiB
C#

using Microsoft.Extensions.Options;
using QMax.Api.Configuration;
namespace QMax.Api.Services;
public sealed class MaxOutboxWorker(
IServiceScopeFactory scopeFactory,
IOptions<QMaxOptions> options,
ILogger<MaxOutboxWorker> logger) : BackgroundService
{
private readonly QMaxOptions _options = options.Value;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var delay = TimeSpan.FromSeconds(Math.Max(1, _options.MaxOutboxPollIntervalSeconds));
await Task.WhenAll(
RunOutboxLoopAsync(
"message outbox",
delay,
(outbox, cancellationToken) => outbox.ProcessPendingMessagesOnceAsync(cancellationToken),
stoppingToken),
RunOutboxLoopAsync(
"chat command outbox",
delay,
(outbox, cancellationToken) => outbox.ProcessPendingChatActionsOnceAsync(cancellationToken),
stoppingToken));
}
private async Task RunOutboxLoopAsync(
string workerName,
TimeSpan delay,
Func<MaxOutboxService, CancellationToken, Task<int>> process,
CancellationToken stoppingToken)
{
using var timer = new PeriodicTimer(delay);
while (!stoppingToken.IsCancellationRequested)
{
try
{
await timer.WaitForNextTickAsync(stoppingToken);
}
catch (OperationCanceledException)
{
break;
}
try
{
await using var scope = scopeFactory.CreateAsyncScope();
var outbox = scope.ServiceProvider.GetRequiredService<MaxOutboxService>();
await process(outbox, stoppingToken);
}
catch (Exception ex)
{
logger.LogWarning(ex, "QMAX {WorkerName} tick failed.", workerName);
}
}
}
}