using Microsoft.Extensions.Logging; using PARR.Core.Common; namespace PARR.Infrastructure.Interval { internal class IntervalService : IIntervalService { private readonly ILogger logger; public IntervalService(ILogger logger) { this.logger = logger; } //public async Task IntervalInitAsync(IntervalHandlerDelegate intervalHandler, TimeSpan interval) public async Task IntervalInitAsync(Func handler, TimeSpan interval) { logger.LogInformation("Инициализация интервального сервиса с интервалом: {Interval}", interval); var nextStart = DateTimeOffset.UtcNow; while (true) { nextStart = DateTimeOffset.UtcNow; logger.LogInformation("Запуск по расписанию. Интервал: {interval}, дата: {nextStart}", interval, nextStart); try { await handler.Invoke(); } catch (Exception ex) { logger.LogError(ex, "Ошибка при выполнении интервального обработчика"); } nextStart = nextStart.Add(interval); logger.LogInformation("Следующая дата запуска: {NextStart}. Интервал: {Interval}.", nextStart, interval); var intervalOffset = nextStart - DateTimeOffset.UtcNow; if (intervalOffset < TimeSpan.Zero) { intervalOffset = TimeSpan.Zero; logger.LogWarning( "Время следующего запуска изменено на текущее время. Рассчитанное время запуска ({NextStart}) меньше текущего времени ({Now}). " + "Это произошло потому что время выполнения основного метода больше чем заданный интервал повторений.", nextStart, DateTimeOffset.UtcNow); } logger.LogDebug("Ожидание {Delay} перед следующим запуском", intervalOffset); await Task.Delay(intervalOffset); } } } }