using Microsoft.EntityFrameworkCore; public class SepsisBundleMonitorService : BackgroundService { private static readonly TimeSpan ScanInterval = TimeSpan.FromMinutes(5); private readonly IServiceProvider _services; private readonly ClinicalMetrics _metrics; private readonly ILogger _logger; public SepsisBundleMonitorService( IServiceProvider services, ClinicalMetrics metrics, ILogger logger) { _services = services; _metrics = metrics; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("Sepsis bundle monitor started. ScanInterval={Interval}", ScanInterval); while (!stoppingToken.IsCancellationRequested) { try { await ScanOverdueBundlesAsync(stoppingToken); } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.LogError(ex, "Sepsis bundle monitor error — will retry on next scan cycle"); } await Task.Delay(ScanInterval, stoppingToken); } } internal async Task ScanOverdueBundlesAsync(CancellationToken ct) { using var scope = _services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var overdue = await db.SepsisBundles .Where(b => b.ComplianceStatus == SepsisBundleComplianceStatus.InProgress && b.DeadlineAt < DateTimeOffset.UtcNow) .ToListAsync(ct); if (overdue.Count == 0) return; foreach (var bundle in overdue) { bundle.ComplianceStatus = SepsisBundleComplianceStatus.NonCompliant; _metrics.SepsisBundleComplianceTotal .WithLabels("NON_COMPLIANT").Inc(); var incompleteCount = await db.SepsisBundleElements .CountAsync(e => e.BundleId == bundle.Id && e.Status != SepsisBundleElementStatus.Completed, ct); _logger.LogWarning( "Sepsis bundle {BundleId} for encounter {EncounterId} marked NON_COMPLIANT — " + "deadline {Deadline} passed with {Incomplete} incomplete elements", bundle.Id, bundle.EncounterId, bundle.DeadlineAt, incompleteCount); } await db.SaveChangesAsync(ct); _logger.LogInformation( "Sepsis bundle monitor marked {Count} overdue bundles as NON_COMPLIANT", overdue.Count); } }