DD.WellWorkover.Cloud/AsbCloudInfrastructure/Background/WorkStore.cs

106 lines
3.3 KiB
C#
Raw Normal View History

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