using System; using System.Collections.Generic; using System.Linq; namespace AsbCloudInfrastructure.Background { /// /// /// Очередь работ /// /// Не периодические задачи будут возвращаться первыми, как самые приоритетные. /// class WorkQueue { private Queue Primary = new(8); private readonly List Periodic = new(8); /// /// Добавление работы. /// /// /// Id mast be unique public void Push(WorkBase work) { if (Periodic.Any(w => w.Id == work.Id)) throw new ArgumentException("work.Id is not unique", nameof(work)); if (Primary.Any(w => w.Id == work.Id)) throw new ArgumentException("work.Id is not unique", nameof(work)); if (work is WorkPeriodic workPeriodic) { Periodic.Add(workPeriodic); return; } Primary.Enqueue(work); } /// /// Удаление работы по ID /// /// /// public bool Delete(string id) { var workPeriodic = Periodic.FirstOrDefault(w => w.Id == id); if (workPeriodic is not null) { Periodic.Remove(workPeriodic); return true; } var work = Primary.FirstOrDefault(w => w.Id == id); if (work is not null) { Primary = new Queue(Primary.Where(w => w.Id != id)); return true; } return false; } public bool Contains(string id) { var result = Periodic.Any(w => w.Id == id) || Primary.Any(w => w.Id == id); return result; } /// /// /// Возвращает приоритетную задачу. /// /// /// Если приоритетные закончились, то ищет ближайшую периодическую. /// Если до старта ближайшей периодической работы меньше 20 сек, /// то этой задаче устанавливается время последнего запуска в now и она возвращается. /// Если больше 20 сек, то возвращается null. /// /// /// /// public WorkBase? Pop() { if (Primary.Any()) return Primary.Dequeue(); var work = GetNextPeriodic(); if (work is null || work.NextStart > DateTime.Now) return null; work.LastStart = DateTime.Now; return work; } private WorkPeriodic? GetNextPeriodic() { var work = Periodic .OrderBy(w => w.NextStart) .ThenByDescending(w => w.Period) .FirstOrDefault(); return work; } } }