using System; using System.Collections.Generic; using System.Linq; namespace AsbCloudInfrastructure.Background; /// /// /// Очередь работ /// /// Не периодические задачи будут возвращаться первыми, как самые приоритетные. /// public class WorkStore { private readonly List periodics = new(8); /// /// Список периодических задач /// public IEnumerable Periodics => periodics; /// /// Работы выполняемые один раз /// public Queue RunOnceQueue { get; private set; } = new(8); /// /// последние 16 завершившиеся с ошибкой /// public CyclycArray Felled { get; } = new(16); /// /// последние 16 успешно завершенных /// public CyclycArray Done { get; } = new(16); /// /// Добавить фоновую работу выполняющуюся с заданным периодом /// /// /// public void AddPeriodic(TimeSpan period) where T : Work, new() { var work = new T(); var periodic = new WorkPeriodic(work, period); periodics.Add(periodic); } /// /// Добавить фоновую работу выполняющуюся с заданным периодом /// /// /// public void AddPeriodic(Work work, TimeSpan period) { var periodic = new WorkPeriodic(work, period); periodics.Add(periodic); } /// /// Удаление работы по ID из одноразовой очереди /// /// /// public bool TryRemoveFromRunOnceQueue(string id) { var work = RunOnceQueue.FirstOrDefault(w => w.Id == id); if (work is not null) { RunOnceQueue = new Queue(RunOnceQueue.Where(w => w.Id != id)); return true; } return false; } /// /// /// Возвращает приоритетную задачу. /// /// /// Если приоритетные закончились, то ищет ближайшую периодическую. /// Если до старта ближайшей периодической работы меньше 20 сек, /// то этой задаче устанавливается время последнего запуска в now и она возвращается. /// Если больше 20 сек, то возвращается null. /// /// /// /// public Work? GetNext() { if (RunOnceQueue.Any()) return RunOnceQueue.Dequeue(); var work = GetNextPeriodic(); if (work is null || work.NextStart > DateTime.Now) return null; return work.Work; } private WorkPeriodic? GetNextPeriodic() { var work = Periodics .OrderBy(w => w.NextStart) .FirstOrDefault(); return work; } }