using Jiaowu.Api.Domain.System; namespace Jiaowu.Api.Infrastructure.BackgroundJobs; public sealed class InMemoryBackgroundJobWorker( InMemoryBackgroundJobTransport transport, BackgroundJobRunner runner, BackgroundJobOptions options, ILogger logger) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { var workers = Enum.GetValues() .SelectMany(kind => Enumerable.Range( 0, options.ConsumerConcurrency(kind)) .Select(_ => ConsumeAsync(kind, stoppingToken))) .ToArray(); try { await Task.WhenAll(workers); } catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) { logger.LogInformation("In-memory background job worker is stopping."); } } private async Task ConsumeAsync( BackgroundJobKind kind, CancellationToken cancellationToken) { await foreach (var message in transport.ReadAllAsync( kind, cancellationToken)) { var result = await runner.RunAsync(message, cancellationToken); if (result.Outcome != BackgroundJobRunOutcome.Retry) continue; await Task.Delay(result.RetryAfter, cancellationToken); await transport.PublishAsync(message, cancellationToken); } } }