using Hcs.WebApp.BackgroundServices.DataParsers; using Hcs.WebApp.Services; using Hcs.WebApp.Utils; namespace Hcs.WebApp.BackgroundServices { public class DataParsingService( DataParsingState state, DataParserFactory dataParserFactory, IServiceScopeFactory scopeFactory, IWebHostEnvironment webHostEnvironment) : BackgroundService { private const int SLEEP_TIME = 30000; private readonly DataParsingState state = state; private readonly DataParserFactory dataParserFactory = dataParserFactory; private readonly IServiceScopeFactory scopeFactory = scopeFactory; private readonly IWebHostEnvironment webHostEnvironment = webHostEnvironment; protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await InitializeStateAsync(); while (!stoppingToken.IsCancellationRequested) { while (state.TryDequeueOperation(out var operation)) { state.SetProcessingOperation(operation); if (stoppingToken.IsCancellationRequested) return; var scope = scopeFactory.CreateScope(); var headquartersService = scope.ServiceProvider.GetRequiredService(); try { var startedAt = DateTime.Now; await headquartersService.SetOperationStartedAsync(operation.Id, startedAt); state.InvokeOnOperationStarted(operation.Id, operation.CampaignId, startedAt); var dataParser = dataParserFactory.CreateDataParser(scope, operation, webHostEnvironment); await dataParser.ParseAsync(); state.InvokeOnOperationEnded(operation.Id, operation.CampaignId, DateTime.Now, string.Empty); } catch (Exception e) { var failedAt = DateTime.Now; var failureReason = e.CombineMessages(); await headquartersService.SetOperationEndedWithFailAsync(operation.Id, failedAt, failureReason); state.InvokeOnOperationEnded(operation.Id, operation.CampaignId, failedAt, failureReason); } state.UnsetProcessingOperation(operation); } await Task.Delay(SLEEP_TIME, stoppingToken); } } private async Task InitializeStateAsync() { using var scope = scopeFactory.CreateScope(); var headquartersService = scope.ServiceProvider.GetRequiredService(); var operations = await headquartersService.GetNotCompletedParseOperationsAsync(); foreach (var operation in operations) { state.EnqueueOperation(operation); } state.Ready = true; } } }