using Extrudex.Domain.Interfaces; using Extrudex.Infrastructure.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Extrudex.API.Jobs; /// /// Background service that periodically syncs Moonraker printer status /// and print job history into the Extrudex database. Runs as a hosted /// service and polls all active Moonraker printers on a configurable /// interval to update printer state and map completed print jobs /// to PrintJob and FilamentUsage entities. /// /// Configuration is bound from the "MoonrakerPrinterSync" section in /// appsettings.json. Set Enabled=false to disable without removing /// the service registration. /// public class MoonrakerPrinterSyncJob : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; private readonly MoonrakerPrinterSyncOptions _options; private readonly ILogger _logger; /// /// Creates a new MoonrakerPrinterSyncJob. /// /// Factory for creating DI scopes to resolve scoped services. /// Configuration options for polling interval and timeouts. /// Logger for diagnostic output. public MoonrakerPrinterSyncJob( IServiceScopeFactory scopeFactory, IOptions options, ILogger logger) { _scopeFactory = scopeFactory; _options = options.Value; _logger = logger; } /// protected override async Task ExecuteAsync(CancellationToken stoppingToken) { if (!_options.Enabled) { _logger.LogInformation("Moonraker printer sync job is disabled via configuration — exiting"); return; } _logger.LogInformation( "Moonraker printer sync job starting — polling every {Interval}", _options.PollingInterval); // Delay briefly on startup to allow the web host to fully initialize await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken); while (!stoppingToken.IsCancellationRequested) { try { using var scope = _scopeFactory.CreateScope(); var syncService = scope.ServiceProvider.GetRequiredService(); var syncedCount = await syncService.SyncAllAsync(stoppingToken); _logger.LogInformation( "Moonraker printer sync completed — {SyncedCount} printer(s) synced. Next sync in {Interval}", syncedCount, _options.PollingInterval); } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.LogError(ex, "Error during Moonraker printer sync cycle — will retry in {Interval}", _options.PollingInterval); } await Task.Delay(_options.PollingInterval, stoppingToken); } _logger.LogInformation("Moonraker printer sync job shutting down"); } }