namespace JobTrackerApi.Services; public sealed class EmailSendAttemptRecoveryHostedService( IServiceScopeFactory scopes, IStartupReadiness startupReadiness, ILogger logger) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await startupReadiness.WaitUntilReadyAsync(stoppingToken); while (!stoppingToken.IsCancellationRequested) { try { await using var scope = scopes.CreateAsyncScope(); var result = await scope.ServiceProvider.GetRequiredService() .ReconcileAbandonedAsync(stoppingToken); if (result.FailedPending > 0 || result.UncertainSending > 0) { logger.LogWarning( "Recovered abandoned email attempts: failedPending={FailedPending}, uncertainSending={UncertainSending}. No provider retry was attempted.", result.FailedPending, result.UncertainSending); } } catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested) { break; } catch (Exception ex) { logger.LogError(ex, "Email send-attempt recovery failed; provider delivery was not attempted."); } try { await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); } catch (OperationCanceledException) { break; } } } }