using Socialize.Api.Infrastructure.Observability; namespace Socialize.Api.Modules.CalendarIntegrations.Services; internal sealed class CalendarImportBackgroundService( IServiceScopeFactory scopeFactory, SocializeMetrics metrics, ILogger logger) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using PeriodicTimer timer = new(TimeSpan.FromHours(6)); while (!stoppingToken.IsCancellationRequested) { await RefreshDueSourcesAsync(stoppingToken); await timer.WaitForNextTickAsync(stoppingToken); } } private async Task RefreshDueSourcesAsync(CancellationToken stoppingToken) { try { using IServiceScope scope = scopeFactory.CreateScope(); CalendarImportSyncService syncService = scope.ServiceProvider.GetRequiredService(); await syncService.RefreshDueSourcesAsync(stoppingToken); metrics.RecordBackgroundJobRun(nameof(CalendarImportBackgroundService), true); } catch (OperationCanceledException ex) when (stoppingToken.IsCancellationRequested) { logger.LogDebug(ex, "Calendar import background sync stopped."); } #pragma warning disable CA1031 // Background service should log and continue after unexpected sync failures. catch (Exception ex) { metrics.RecordBackgroundJobRun(nameof(CalendarImportBackgroundService), false); logger.LogError(ex, "Calendar import background sync failed."); } #pragma warning restore CA1031 } }