using System.Threading; using Microsoft.Extensions.DependencyInjection; using NCrontab; using LCU.Api.Internal.DispatcherSharedLib.Utilities; using LCU.Api.Internal.Dispatcher.Configurations; using LCU.Api.Internal.Dispatcher.Services.DispatcherOperationServices; using LCU.Library.Internal.LCUHostedService.LCUBackgroundService; namespace LCU.Api.Internal.Dispatcher.HostedServices; public class BatchErroredJobsHostedService : LCUBackgroundService, IBatchErroredJobsHostedService { private readonly ApiConfiguration _apiConfiguration; private readonly IServiceScopeFactory _scopeFactory; private readonly CrontabSchedule _batchErroredJobsSchedule; private DateTime _nextScheduleRun; public const string DefaultBatchErroredJobsCronPattern = "*/15 * * * *"; private CancellationToken _cancellationToken; public BatchErroredJobsHostedService(IServiceScopeFactory scopeFactory, ApiConfiguration apiConfiguration) { _scopeFactory = scopeFactory; _apiConfiguration = apiConfiguration; _batchErroredJobsSchedule = CronHelpers.SetCronSchedule(_apiConfiguration.BatchErroredJobsCronSchedule, DefaultBatchErroredJobsCronPattern); _nextScheduleRun = _batchErroredJobsSchedule.GetNextOccurrence(DateTime.Now); _cancellationToken = new CancellationToken(); } protected override async Task ExecuteAsync(CancellationToken cancellationToken) { if (!_apiConfiguration.FeatureFlags.RunBatchErroredJobsHostedService) { Log.Error("Batch Errored Jobs Hosted Service is disabled by feature flag. Service not started."); return; } Log.Debug("Dispatcher's Batch Errored Jobs Hosted Service is starting."); try { while (!cancellationToken.IsCancellationRequested) { await Task.Delay(UntilNextExecution(), cancellationToken); // wait until next time using (var scope = _scopeFactory.CreateAsyncScope()) { Log.Debug("Running Batch Errored Jobs Service"); await scope.ServiceProvider.GetRequiredService().PerformBatchErroredJobs(_cancellationToken); } _nextScheduleRun = _batchErroredJobsSchedule.GetNextOccurrence(DateTime.Now); } } catch(OperationCanceledException taskCanceledEx) { Log.Error(taskCanceledEx, $"Manual start/stop of Dispatcher's Batch Errored Jobs Hosted Service was initiated."); } catch (Exception exception) { Log.Error(exception, "Error trying to startup main thread for Dispatcher's Batch Errored Jobs Hosted Service"); } Log.Debug("Dispatcher's Batch Errored Jobs Hosted Service is stopping."); } private int UntilNextExecution() => Math.Max(0, (int)_nextScheduleRun.Subtract(DateTime.Now).TotalMilliseconds); }