forked from ddrilling/AsbCloudServer
Refactor webStore
This commit is contained in:
parent
724c7b0cd8
commit
1560c6bf91
@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace AsbCloudInfrastructure.Background
|
||||
namespace AsbCloudApp.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Информация о фоновой работе
|
||||
/// </summary>
|
||||
public class BackgroudWorkDto
|
||||
{
|
||||
/// <summary>
|
||||
@ -10,6 +13,9 @@ namespace AsbCloudInfrastructure.Background
|
||||
/// </summary>
|
||||
public string Id { get; init; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Класс описания состояния
|
||||
/// </summary>
|
||||
public class CurrentStateInfo
|
||||
{
|
||||
private string state = "start";
|
||||
@ -37,6 +43,9 @@ namespace AsbCloudInfrastructure.Background
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Прогресс
|
||||
/// </summary>
|
||||
public double Progress { get; internal set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
@ -45,9 +54,12 @@ namespace AsbCloudInfrastructure.Background
|
||||
public DateTime StateUpdate { get; private set; } = DateTime.Now;
|
||||
}
|
||||
|
||||
public class LastErrorInfo: LastCompleteInfo
|
||||
/// <summary>
|
||||
/// Инфо о последней ошибке
|
||||
/// </summary>
|
||||
public class LastErrorInfo : LastCompleteInfo
|
||||
{
|
||||
public LastErrorInfo(CurrentStateInfo state, string errorText)
|
||||
public LastErrorInfo(CurrentStateInfo state, string errorText)
|
||||
: base(state)
|
||||
{
|
||||
ErrorText = errorText;
|
||||
@ -59,12 +71,15 @@ namespace AsbCloudInfrastructure.Background
|
||||
public string ErrorText { get; init; } = null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Инфо о последнем завершении
|
||||
/// </summary>
|
||||
public class LastCompleteInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Дата запуска
|
||||
/// </summary>
|
||||
public DateTime Start {get; init;}
|
||||
public DateTime Start { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата завершения
|
||||
@ -123,9 +138,12 @@ namespace AsbCloudInfrastructure.Background
|
||||
/// Максимально допустимое время выполнения работы
|
||||
/// </summary>
|
||||
public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(1);
|
||||
|
||||
|
||||
private string WorkNameForTrace => $"Backgroud work:\"{Id}\"";
|
||||
|
||||
/// <summary>
|
||||
/// Обновления состояния при запуске работы
|
||||
/// </summary>
|
||||
protected void SetStatusStart()
|
||||
{
|
||||
CurrentState = new();
|
||||
@ -133,6 +151,9 @@ namespace AsbCloudInfrastructure.Background
|
||||
Trace.TraceInformation($"{WorkNameForTrace} state: starting");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обновления состояния в процессе работы
|
||||
/// </summary>
|
||||
protected void UpdateStatus(string newState, double? progress)
|
||||
{
|
||||
if (CurrentState is null)
|
||||
@ -145,17 +166,23 @@ namespace AsbCloudInfrastructure.Background
|
||||
Trace.TraceInformation($"{WorkNameForTrace} state: {newState}");
|
||||
}
|
||||
|
||||
protected void SetStatusComplete(System.Threading.Tasks.TaskStatus status)
|
||||
/// <summary>
|
||||
/// Обновления состояния при успешном завершении работы
|
||||
/// </summary>
|
||||
protected void SetStatusComplete()
|
||||
{
|
||||
if (CurrentState is null)
|
||||
return;
|
||||
|
||||
LastComplete = new (CurrentState);
|
||||
LastComplete = new(CurrentState);
|
||||
CurrentState = null;
|
||||
CountComplete++;
|
||||
Trace.TraceInformation($"{WorkNameForTrace} state: completed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обновления состояния при ошибке в работе
|
||||
/// </summary>
|
||||
protected void SetLastError(string errorMessage)
|
||||
{
|
||||
if (CurrentState is null)
|
@ -1,78 +1,49 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Background
|
||||
namespace AsbCloudInfrastructure.Background;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис для фонового выполнения работы
|
||||
/// </summary>
|
||||
public class BackgroundWorker : BackgroundService
|
||||
{
|
||||
/// <summary>
|
||||
/// Сервис для фонового выполнения работы
|
||||
/// </summary>
|
||||
public class BackgroundWorker : BackgroundService
|
||||
private static readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10);
|
||||
private static readonly TimeSpan minDelay = TimeSpan.FromSeconds(2);
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
public WorkStore WorkStore { get; } = new WorkStore();
|
||||
public Work? CurrentWork;
|
||||
|
||||
public BackgroundWorker(IServiceProvider serviceProvider)
|
||||
{
|
||||
private static readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10);
|
||||
private static readonly TimeSpan minDelay = TimeSpan.FromSeconds(2);
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly WorkStore workQueue = new WorkStore();
|
||||
public string? CurrentWorkId;
|
||||
this.serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public BackgroundWorker(IServiceProvider serviceProvider)
|
||||
protected override async Task ExecuteAsync(CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
this.serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавление задачи в очередь.
|
||||
/// Не периодические задачи будут выполняться вперед.
|
||||
/// </summary>
|
||||
/// <param name="work"></param>
|
||||
/// <exception cref="ArgumentException">Id mast be unique</exception>
|
||||
public void Push(WorkBase work)
|
||||
{
|
||||
workQueue.Push(work);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет наличие работы с указанным Id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool Contains(string id)
|
||||
{
|
||||
return workQueue.Contains(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление работы по ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public bool Delete(string id)
|
||||
{
|
||||
return workQueue.Delete(id);
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
var work = WorkStore.GetNext();
|
||||
if (work is null)
|
||||
{
|
||||
var work = workQueue.Pop();
|
||||
if (work is null)
|
||||
{
|
||||
await Task.Delay(executePeriod, token);
|
||||
continue;
|
||||
}
|
||||
|
||||
CurrentWorkId = work.Id;
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
|
||||
await work.Start(scope.ServiceProvider, token);
|
||||
|
||||
CurrentWorkId = null;
|
||||
await Task.Delay(minDelay, token);
|
||||
await Task.Delay(executePeriod, token);
|
||||
continue;
|
||||
}
|
||||
|
||||
CurrentWork = work;
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
|
||||
var result = await work.Start(scope.ServiceProvider, token);
|
||||
|
||||
if (!result)
|
||||
WorkStore.Falled.Add(work);
|
||||
|
||||
CurrentWork = null;
|
||||
await Task.Delay(minDelay, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using AsbCloudApp.Data;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -8,9 +9,9 @@ namespace AsbCloudInfrastructure.Background
|
||||
/// Класс разовой работы.
|
||||
/// Разовая работа приоритетнее периодической.
|
||||
/// </summary>
|
||||
public class WorkBase : BackgroudWorkDto
|
||||
public class Work : BackgroudWorkDto
|
||||
{
|
||||
internal Func<string, IServiceProvider, Action<string, double?>, CancellationToken, Task> ActionAsync { get; }
|
||||
private Func<string, IServiceProvider, Action<string, double?>, CancellationToken, Task> ActionAsync { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Делегат обработки ошибки.
|
||||
@ -48,7 +49,7 @@ namespace AsbCloudInfrastructure.Background
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </param>
|
||||
public WorkBase(string id, Func<string, IServiceProvider, Action<string, double?>, CancellationToken, Task> actionAsync)
|
||||
public Work(string id, Func<string, IServiceProvider, Action<string, double?>, CancellationToken, Task> actionAsync)
|
||||
{
|
||||
Id = id;
|
||||
ActionAsync = actionAsync;
|
||||
@ -67,7 +68,7 @@ namespace AsbCloudInfrastructure.Background
|
||||
{
|
||||
var task = ActionAsync(Id, services, UpdateStatus, token);
|
||||
await task.WaitAsync(Timeout, token);
|
||||
SetStatusComplete(task.Status);
|
||||
SetStatusComplete();
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
@ -1,45 +1,42 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudInfrastructure.Background
|
||||
namespace AsbCloudInfrastructure.Background;
|
||||
|
||||
/// <summary>
|
||||
/// Класс периодической работы.
|
||||
/// </summary>
|
||||
public class WorkPeriodic
|
||||
{
|
||||
public Work Work { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Класс периодической работы.
|
||||
/// Период выполнения задачи
|
||||
/// </summary>
|
||||
public class WorkPeriodic : WorkBase
|
||||
public TimeSpan Period { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Время следующего запуска
|
||||
/// </summary>
|
||||
public DateTime NextStart
|
||||
{
|
||||
/// <summary>
|
||||
/// Период выполнения задачи
|
||||
/// </summary>
|
||||
public TimeSpan Period { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Время следующего запуска
|
||||
/// </summary>
|
||||
public DateTime NextStart
|
||||
get
|
||||
{
|
||||
get
|
||||
{
|
||||
var lastStart = LastComplete?.Start ?? DateTime.MinValue;
|
||||
if (LastError?.Start > lastStart)
|
||||
lastStart = LastError.Start;
|
||||
return lastStart + Period;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс периодической работы
|
||||
/// </summary>
|
||||
/// <param name="id">Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки</param>
|
||||
/// <param name="actionAsync">Делегат работы</param>
|
||||
/// <param name="period">Период выполнения задачи</param>
|
||||
public WorkPeriodic(string id, Func<string, IServiceProvider, Action<string, double?>, CancellationToken, Task> actionAsync, TimeSpan period)
|
||||
: base(id, actionAsync)
|
||||
{
|
||||
Period = period;
|
||||
var lastStart = Work.LastComplete?.Start ?? DateTime.MinValue;
|
||||
if (Work.LastError?.Start > lastStart)
|
||||
lastStart = Work.LastError.Start;
|
||||
return lastStart + Period;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Класс периодической работы
|
||||
/// </summary>
|
||||
/// <param name="id">Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки</param>
|
||||
/// <param name="actionAsync">Делегат работы</param>
|
||||
/// <param name="period">Период выполнения задачи</param>
|
||||
public WorkPeriodic(Work work, TimeSpan period)
|
||||
{
|
||||
Work = work;
|
||||
Period = period;
|
||||
}
|
||||
}
|
||||
|
@ -2,118 +2,85 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace AsbCloudInfrastructure.Background
|
||||
namespace AsbCloudInfrastructure.Background;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Очередь работ
|
||||
/// </para>
|
||||
/// Не периодические задачи будут возвращаться первыми, как самые приоритетные.
|
||||
/// </summary>
|
||||
public class WorkStore
|
||||
{
|
||||
private readonly List<WorkPeriodic> periodics = new(8);
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Очередь работ
|
||||
/// </para>
|
||||
/// Не периодические задачи будут возвращаться первыми, как самые приоритетные.
|
||||
/// Список периодических задач
|
||||
/// </summary>
|
||||
class WorkStore
|
||||
public IEnumerable<WorkPeriodic> Periodics => periodics;
|
||||
/// <summary>
|
||||
/// Работы выполняемые один раз
|
||||
/// </summary>
|
||||
public Queue<Work> RunOnceQueue { get; private set; } = new(8);
|
||||
|
||||
/// <summary>
|
||||
/// Завершывшиеся с ошибкой
|
||||
/// </summary>
|
||||
public CyclycArray<Work> Falled { get; } = new(16);
|
||||
|
||||
public void AddPeriodic(Work work, TimeSpan period)
|
||||
{
|
||||
private readonly List<WorkPeriodic> Periodic = new(8);
|
||||
|
||||
/// <summary>
|
||||
/// Работы выполняемые один раз
|
||||
/// </summary>
|
||||
public Queue<WorkBase> RunOnceQueue { get; } = new(8);
|
||||
|
||||
/// <summary>
|
||||
/// Работы выполняемые периодически
|
||||
/// </summary>
|
||||
public IOrderedEnumerable<WorkPeriodic> Periodics => Periodic.OrderBy(work => work.NextStart);
|
||||
|
||||
/// <summary>
|
||||
/// Завершывшиеся с ошибкой
|
||||
/// </summary>
|
||||
public CyclycArray<WorkBase> Falled { get; } = new(16);
|
||||
|
||||
/// <summary>
|
||||
/// Добавление работы.
|
||||
/// </summary>
|
||||
/// <param name="work"></param>
|
||||
/// <exception cref="ArgumentException">Id mast be unique</exception>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление работы по ID
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
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<WorkBase>(Primary.Where(w => w.Id != id));
|
||||
// return true;
|
||||
//}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Contains(string id)
|
||||
{
|
||||
var result = false;//Periodic.Any(w => w.Id == id) || Primary.Any(w => w.Id == id);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Возвращает приоритетную задачу.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Если приоритетные закончились, то ищет ближайшую периодическую.
|
||||
/// Если до старта ближайшей периодической работы меньше 20 сек,
|
||||
/// то этой задаче устанавливается время последнего запуска в now и она возвращается.
|
||||
/// Если больше 20 сек, то возвращается null.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="maxTimeToNextWork"></param>
|
||||
/// <returns></returns>
|
||||
public WorkBase? Pop()
|
||||
{
|
||||
//if (Primary.Any())
|
||||
// return Primary.Dequeue();
|
||||
|
||||
var work = GetNextPeriodic();
|
||||
if (work is null || work.NextStart > DateTime.Now)
|
||||
return null;
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
private WorkPeriodic? GetNextPeriodic()
|
||||
{
|
||||
var work = Periodic
|
||||
.OrderBy(w => w.NextStart)
|
||||
.ThenByDescending(w => w.Period)
|
||||
.FirstOrDefault();
|
||||
return work;
|
||||
}
|
||||
var periodic = new WorkPeriodic(work, period);
|
||||
periodics.Add(periodic);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
RunOnceQueue = new Queue<Work>(RunOnceQueue.Where(w => w.Id != id));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||
public static class OperationDetectionWorkFactory
|
||||
{
|
||||
private const string workId = "Operation detection";
|
||||
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
|
||||
private static string progress = "no progress";
|
||||
|
||||
private static readonly DetectorAbstract[] detectors = new DetectorAbstract[]
|
||||
@ -32,18 +31,16 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
|
||||
//new DetectorTemplatingWhileDrilling(),
|
||||
};
|
||||
|
||||
public static WorkPeriodic MakeWork()
|
||||
{
|
||||
var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod);
|
||||
workPeriodic.Timeout = TimeSpan.FromSeconds(15 * 60);
|
||||
workPeriodic.OnErrorAsync = (id, exception, token) =>
|
||||
public static Work MakeWork() => new Work(workId, WorkAction)
|
||||
{
|
||||
var text = $"work {id}, when {progress}, throw error:{exception.Message}";
|
||||
Trace.TraceWarning(text);
|
||||
return Task.CompletedTask;
|
||||
Timeout = TimeSpan.FromMinutes(20),
|
||||
OnErrorAsync = (id, exception, token) =>
|
||||
{
|
||||
var text = $"work {id}, when {progress}, throw error:{exception.Message}";
|
||||
Trace.TraceWarning(text);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
return workPeriodic;
|
||||
}
|
||||
|
||||
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
|
||||
private static async Task WorkAction(string _, IServiceProvider serviceProvider, Action<string, double?> onProgress, CancellationToken token)
|
||||
|
@ -513,7 +513,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
if (state.IdState == idStateCreating)
|
||||
{
|
||||
var workId = MakeWorkId(idWell);
|
||||
if (!backgroundWorker.Contains(workId))
|
||||
if (!backgroundWorker.WorkStore.RunOnceQueue.Any(w => w.Id == workId))
|
||||
{
|
||||
var well = (await wellService.GetOrDefaultAsync(idWell, token))!;
|
||||
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.pdf";
|
||||
@ -540,12 +540,12 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
var work = new WorkBase(workId, workAction)
|
||||
var work = new Work(workId, workAction)
|
||||
{
|
||||
OnErrorAsync = onErrorAction
|
||||
};
|
||||
|
||||
backgroundWorker.Push(work);
|
||||
backgroundWorker.WorkStore.RunOnceQueue.Enqueue(work);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -559,7 +559,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
||||
private async Task<int> RemoveDrillingProgramAsync(int idWell, CancellationToken token)
|
||||
{
|
||||
var workId = MakeWorkId(idWell);
|
||||
backgroundWorker.Delete(workId);
|
||||
backgroundWorker.WorkStore.TryRemoveFromRunOnceQueue(workId);
|
||||
|
||||
var filesIds = await context.Files
|
||||
.Where(f => f.IdWell == idWell &&
|
||||
|
@ -52,12 +52,12 @@ namespace AsbCloudInfrastructure.Services.Email
|
||||
}
|
||||
|
||||
var workId = MakeWorkId(notification.IdUser, notification.Title, notification.Message);
|
||||
if (!backgroundWorker.Contains(workId))
|
||||
if (!backgroundWorker.WorkStore.RunOnceQueue.Any(w=>w.Id==workId))
|
||||
{
|
||||
var workAction = MakeEmailSendWorkAction(notification);
|
||||
|
||||
var work = new WorkBase(workId, workAction);
|
||||
backgroundWorker.Push(work);
|
||||
var work = new Work(workId, workAction);
|
||||
backgroundWorker.WorkStore.RunOnceQueue.Enqueue(work);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
|
@ -16,16 +16,11 @@ namespace AsbCloudInfrastructure.Services
|
||||
internal static class LimitingParameterCalcWorkFactory
|
||||
{
|
||||
private const string workId = "Limiting parameter calc";
|
||||
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
|
||||
|
||||
public static WorkPeriodic MakeWork()
|
||||
{
|
||||
var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod)
|
||||
public static Work MakeWork() => new Work(workId, WorkAction)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(30)
|
||||
};
|
||||
return workPeriodic;
|
||||
}
|
||||
|
||||
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
|
||||
private static async Task WorkAction(string _, IServiceProvider serviceProvider, Action<string, double?> onProgress, CancellationToken token)
|
||||
|
@ -94,8 +94,8 @@ namespace AsbCloudInfrastructure.Services
|
||||
context.SaveChanges();
|
||||
};
|
||||
|
||||
var work = new WorkBase(workId, workAction);
|
||||
backgroundWorkerService.Push(work);
|
||||
var work = new Work(workId, workAction);
|
||||
backgroundWorkerService.WorkStore.RunOnceQueue.Enqueue(work);
|
||||
|
||||
progressHandler.Invoke(new ReportProgressDto
|
||||
{
|
||||
|
@ -48,12 +48,12 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
instance = new TelemetryDataCache<TDto>();
|
||||
var worker = provider.GetRequiredService<BackgroundWorker>();
|
||||
var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
|
||||
var work = new WorkBase(workId, async (workId, provider, onProgress, token) => {
|
||||
var work = new Work(workId, async (workId, provider, onProgress, token) => {
|
||||
var db = provider.GetRequiredService<IAsbCloudDbContext>();
|
||||
await instance.InitializeCacheFromDBAsync<TEntity>(db, onProgress, token);
|
||||
});
|
||||
|
||||
worker.Push(work);
|
||||
worker.WorkStore.RunOnceQueue.Enqueue(work);
|
||||
}
|
||||
instance.provider = provider;
|
||||
return instance;
|
||||
@ -168,7 +168,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
|
||||
.Where(well => well.IdTelemetry != null)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var count = wells.Count();
|
||||
var count = wells.Length;
|
||||
var i = 0;
|
||||
foreach (Well well in wells)
|
||||
{
|
||||
|
@ -18,7 +18,6 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
internal static class SubsystemOperationTimeCalcWorkFactory
|
||||
{
|
||||
private const string workId = "Subsystem operation time calc";
|
||||
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
|
||||
|
||||
private const int idSubsytemTorqueMaster = 65537;
|
||||
private const int idSubsytemSpinMaster = 65536;
|
||||
@ -26,14 +25,10 @@ namespace AsbCloudInfrastructure.Services.Subsystems
|
||||
private const int idSubsystemAPDSlide = 12;
|
||||
private const int idSubsytemMse = 2;
|
||||
|
||||
public static WorkPeriodic MakeWork()
|
||||
{
|
||||
var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(30)
|
||||
};
|
||||
return workPeriodic;
|
||||
}
|
||||
public static Work MakeWork() => new Work(workId, WorkAction)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(20)
|
||||
};
|
||||
|
||||
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
|
||||
private static async Task WorkAction(string _, IServiceProvider serviceProvider, Action<string, double?> onProgress, CancellationToken token)
|
||||
|
@ -29,7 +29,6 @@ namespace AsbCloudInfrastructure.Services
|
||||
}
|
||||
|
||||
private const string workId = "Well statistics update";
|
||||
private static readonly TimeSpan workPeriod = TimeSpan.FromMinutes(30);
|
||||
|
||||
private readonly TelemetryDataCache<TelemetryDataSaubDto> telemetryDataSaubCache;
|
||||
private readonly TelemetryDataCache<TelemetryDataSpinDto> telemetryDataSpinCache;
|
||||
@ -53,14 +52,10 @@ namespace AsbCloudInfrastructure.Services
|
||||
this.gtrRepository = gtrRepository;
|
||||
}
|
||||
|
||||
public static WorkPeriodic MakeWork()
|
||||
{
|
||||
var workPeriodic = new WorkPeriodic(workId, WorkAction, workPeriod)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(30)
|
||||
};
|
||||
return workPeriodic;
|
||||
}
|
||||
public static Work MakeWork() => new Work(workId, WorkAction)
|
||||
{
|
||||
Timeout = TimeSpan.FromMinutes(20)
|
||||
};
|
||||
|
||||
private static async Task WorkAction(string workName, IServiceProvider serviceProvider, Action<string, double?> onProgress, CancellationToken token)
|
||||
{
|
||||
|
@ -15,7 +15,6 @@ using AsbCloudInfrastructure.Services.SAUB;
|
||||
|
||||
namespace AsbCloudInfrastructure
|
||||
{
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public static void BeforeRunHandler(IHost host)
|
||||
@ -32,11 +31,11 @@ namespace AsbCloudInfrastructure
|
||||
_ = provider.GetRequiredService<TelemetryDataCache<TelemetryDataSpinDto>>();
|
||||
|
||||
var backgroundWorker = provider.GetRequiredService<BackgroundWorker>();
|
||||
backgroundWorker.Push(WellInfoService.MakeWork());
|
||||
backgroundWorker.Push(OperationDetectionWorkFactory.MakeWork());
|
||||
backgroundWorker.Push(SubsystemOperationTimeCalcWorkFactory.MakeWork());
|
||||
backgroundWorker.Push(LimitingParameterCalcWorkFactory.MakeWork());
|
||||
backgroundWorker.Push(MakeMemoryMonitoringWork());
|
||||
backgroundWorker.WorkStore.AddPeriodic(WellInfoService.MakeWork(), TimeSpan.FromMinutes(30));
|
||||
backgroundWorker.WorkStore.AddPeriodic(OperationDetectionWorkFactory.MakeWork(), TimeSpan.FromMinutes(15));
|
||||
backgroundWorker.WorkStore.AddPeriodic(SubsystemOperationTimeCalcWorkFactory.MakeWork(), TimeSpan.FromMinutes(30));
|
||||
backgroundWorker.WorkStore.AddPeriodic(LimitingParameterCalcWorkFactory.MakeWork(), TimeSpan.FromMinutes(30));
|
||||
backgroundWorker.WorkStore.AddPeriodic(MakeMemoryMonitoringWork(), TimeSpan.FromMinutes(1));
|
||||
|
||||
var notificationBackgroundWorker = provider.GetRequiredService<NotificationBackgroundWorker>();
|
||||
|
||||
@ -48,17 +47,15 @@ namespace AsbCloudInfrastructure
|
||||
});
|
||||
}
|
||||
|
||||
static WorkPeriodic MakeMemoryMonitoringWork()
|
||||
static Work MakeMemoryMonitoringWork()
|
||||
{
|
||||
var workId = "Memory monitoring";
|
||||
var workAction = (string _, IServiceProvider _, Action<string, double?> _, CancellationToken _) => {
|
||||
var bytes = GC.GetTotalMemory(false);
|
||||
var bytesString = FromatBytes(bytes);
|
||||
System.Diagnostics.Trace.TraceInformation($"Total memory allocated is {bytesString} bytes. DbContext count is:{AsbCloudDbContext.ReferenceCount}");
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
var workPeriod = TimeSpan.FromMinutes(1);
|
||||
var work = new WorkPeriodic(workId, workAction, workPeriod);
|
||||
var work = new Work("Memory monitoring", workAction);
|
||||
return work;
|
||||
}
|
||||
|
||||
|
@ -366,7 +366,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, state.IdState);
|
||||
backgroundWorkerMock.Verify(s => s.Push(It.IsAny<WorkBase>()));
|
||||
backgroundWorkerMock.Verify(s => s.Push(It.IsAny<Work>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -29,12 +29,12 @@ public class SignalRNotificationTransportService : INotificationTransportService
|
||||
{
|
||||
var workId = HashCode.Combine(notifications.Select(n => n.Id)).ToString("x");
|
||||
|
||||
if (backgroundWorker.Contains(workId))
|
||||
if (backgroundWorker.WorkStore.RunOnceQueue.Any(w => w.Id == workId))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var workAction = MakeSignalRSendWorkAction(notifications);
|
||||
var work = new WorkBase(workId, workAction);
|
||||
backgroundWorker.Push(work);
|
||||
var work = new Work(workId, workAction);
|
||||
backgroundWorker.WorkStore.RunOnceQueue.Enqueue(work);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user