From 673cb8960cd92ae5037700f362575618e1d387d8 Mon Sep 17 00:00:00 2001 From: Frolov-Nikita Date: Sun, 8 Oct 2023 13:09:09 +0500 Subject: [PATCH] =?UTF-8?q?WorkBase=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20?= =?UTF-8?q?=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D1=81=D0=BA=D0=BE=D0=B9=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=86=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Background/BackgroundWorker.cs | 26 +--- AsbCloudInfrastructure/Background/WorkBase.cs | 113 ++++++++++++++++-- .../Background/WorkPeriodic.cs | 2 +- .../Background/WorkQueue.cs | 2 - AsbCloudInfrastructure/Background/todo.md | 9 +- .../DrillingProgram/DrillingProgramService.cs | 1 - .../BackgroundWorkerServiceTest.cs | 2 +- 7 files changed, 120 insertions(+), 35 deletions(-) diff --git a/AsbCloudInfrastructure/Background/BackgroundWorker.cs b/AsbCloudInfrastructure/Background/BackgroundWorker.cs index 7c88fade..4ba3d535 100644 --- a/AsbCloudInfrastructure/Background/BackgroundWorker.cs +++ b/AsbCloudInfrastructure/Background/BackgroundWorker.cs @@ -14,10 +14,10 @@ namespace AsbCloudInfrastructure.Background { private static readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10); private static readonly TimeSpan minDelay = TimeSpan.FromSeconds(2); - private static readonly TimeSpan exceptionHandleTimeout = TimeSpan.FromSeconds(2); private readonly IServiceProvider serviceProvider; private readonly WorkQueue workQueue = new WorkQueue(); public string? CurrentWorkId; + public BackgroundWorker(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; @@ -58,36 +58,18 @@ namespace AsbCloudInfrastructure.Background { while (!token.IsCancellationRequested) { - var dateStart = DateTime.Now; var work = workQueue.Pop(); if (work is null) { await Task.Delay(executePeriod, token); continue; } + CurrentWorkId = work.Id; using var scope = serviceProvider.CreateScope(); - - try - { - Trace.TraceInformation($"Backgroud work:\"{work.Id}\" start."); - var task = work.ActionAsync(work.Id, scope.ServiceProvider, token); - await task.WaitAsync(work.Timeout, token); - work.ExecutionTime = DateTime.Now - dateStart; - Trace.TraceInformation($"Backgroud work:\"{work.Id}\" done. ExecutionTime: {work.ExecutionTime:hh\\:mm\\:ss\\.fff}"); - } - catch (Exception exception) - { - Trace.TraceError($"Backgroud work:\"{work.Id}\" throw exception: {exception.Message}"); - if (work.OnErrorAsync is not null) - { - using var task = Task.Run( - async () => await work.OnErrorAsync(work.Id, exception, token), - token); - await task.WaitAsync(exceptionHandleTimeout, token); - } - } + await work.Start(scope.ServiceProvider, token); + CurrentWorkId = null; await Task.Delay(minDelay, token); } diff --git a/AsbCloudInfrastructure/Background/WorkBase.cs b/AsbCloudInfrastructure/Background/WorkBase.cs index e8adf04c..ef238a85 100644 --- a/AsbCloudInfrastructure/Background/WorkBase.cs +++ b/AsbCloudInfrastructure/Background/WorkBase.cs @@ -1,10 +1,11 @@ using System; +using System.Diagnostics; +using System.Text; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Background { - /// /// Класс разовой работы. /// Разовая работа приоритетнее периодической. @@ -14,7 +15,7 @@ namespace AsbCloudInfrastructure.Background /// /// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки. /// - public string Id { get; private set; } + public string Id { get; } /// /// Делегат работы. @@ -36,7 +37,7 @@ namespace AsbCloudInfrastructure.Background /// /// /// - internal Func ActionAsync { get; set; } + internal Func ActionAsync { get; } /// /// Делегат обработки ошибки. @@ -50,20 +51,118 @@ namespace AsbCloudInfrastructure.Background public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(1); /// - /// Фактическое время успешного выполнения работы + /// Продолжительность последнего выполнения /// - public TimeSpan? ExecutionTime { get; internal set; } + public TimeSpan? LastExecutionTime { get; private set; } + + /// + /// Текущее время выполнения + /// + public TimeSpan? CurrentExecutionTime => CurrentStart.HasValue + ? DateTime.Now - CurrentStart.Value + : null; /// /// Время последнего запуска /// - public DateTime LastStart { get; set; } + public DateTime? CurrentStart { get; private set; } + + /// + /// Текстовое описание того, что происходит в задаче. + /// + public string? CurrentStatus { get; private set; } + + /// + /// Время последнего запуска + /// + public DateTime? CurrentStatusUpdate { get; private set; } + + /// + /// Последняя ошибка + /// + public string? LastErrorMessage { get; private set; } + + /// + /// Дата последнего запуска + /// + public DateTime? LastStart { get; private set; } + + /// + /// Дата последней ошибки + /// + public DateTime? LastError { get; private set; } + + /// + /// Дата завершения последнего выполнения + /// + public DateTime? LastComplete { get; private set; } + + /// + /// Кол-во завершений + /// + public int CountComplete { get; private set; } + + /// + /// Кол-во ошибок + /// + public int CountErrors { get; private set; } + + private string WorkNameForTrace => $"Backgroud work:\"{Id}\""; public WorkBase(string id, Func actionAsync) { Id = id; ActionAsync = actionAsync; } - } + + public async Task Start(IServiceProvider services, CancellationToken token) + { + CurrentStart = DateTime.Now; + LastStart = DateTime.Now; + try + { + SetStatus(" start"); + var task = ActionAsync(Id, services, token); + await task.WaitAsync(Timeout, token); + LastComplete = DateTime.Now; + CountComplete++; + SetStatus($" {task.Status}. ExecutionTime: {CurrentExecutionTime:hh\\:mm\\:ss\\.fff}"); + } + catch (Exception exception) + { + SetError(exception.Message); + if (OnErrorAsync is not null) + { + var task = Task.Run( + async () => await OnErrorAsync(Id, exception, token), + token); + await task.WaitAsync(Timeout, token); + } + } + LastExecutionTime = CurrentExecutionTime; + CurrentStart = null; + SetStatus(null); + } + + protected void SetStatus(string? newStatus) + { + CurrentStatus = newStatus; + if (newStatus is not null) + { + CurrentStatusUpdate = DateTime.Now; + Trace.TraceInformation($"{WorkNameForTrace} state: {newStatus}"); + } + else + CurrentStatusUpdate = null; + } + + private void SetError(string? errorMessage) + { + CountErrors++; + LastErrorMessage = errorMessage; + LastError = DateTime.Now; + Trace.TraceError($"{WorkNameForTrace} throw exception[{CountErrors}]: {errorMessage}"); + } + } } diff --git a/AsbCloudInfrastructure/Background/WorkPeriodic.cs b/AsbCloudInfrastructure/Background/WorkPeriodic.cs index cbd34fec..5c2b0e23 100644 --- a/AsbCloudInfrastructure/Background/WorkPeriodic.cs +++ b/AsbCloudInfrastructure/Background/WorkPeriodic.cs @@ -18,7 +18,7 @@ namespace AsbCloudInfrastructure.Background /// /// Время следующего запуска /// - public DateTime NextStart => LastStart + Period; + public DateTime NextStart => LastStart??DateTime.MinValue + Period; /// /// Класс периодической работы diff --git a/AsbCloudInfrastructure/Background/WorkQueue.cs b/AsbCloudInfrastructure/Background/WorkQueue.cs index ce77fa94..e925916b 100644 --- a/AsbCloudInfrastructure/Background/WorkQueue.cs +++ b/AsbCloudInfrastructure/Background/WorkQueue.cs @@ -4,7 +4,6 @@ using System.Linq; namespace AsbCloudInfrastructure.Background { - /// /// /// Очередь работ @@ -90,7 +89,6 @@ namespace AsbCloudInfrastructure.Background if (work is null || work.NextStart > DateTime.Now) return null; - work.LastStart = DateTime.Now; return work; } diff --git a/AsbCloudInfrastructure/Background/todo.md b/AsbCloudInfrastructure/Background/todo.md index f30ce6c4..b8b30852 100644 --- a/AsbCloudInfrastructure/Background/todo.md +++ b/AsbCloudInfrastructure/Background/todo.md @@ -1,5 +1,12 @@ # -- +- . + - , + - , + - , - . . - / - / + +# +- dto +- , . diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index adb410d6..9dc20155 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -541,7 +541,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram var work = new WorkBase(workId, workAction) { - ExecutionTime = TimeSpan.FromMinutes(1), OnErrorAsync = onErrorAction }; diff --git a/AsbCloudWebApi.Tests/ServicesTests/BackgroundWorkerServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/BackgroundWorkerServiceTest.cs index 133f6b36..f4a03f2f 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/BackgroundWorkerServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/BackgroundWorkerServiceTest.cs @@ -88,7 +88,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests await BackgroundWorker.StartAsync(CancellationToken.None); await Task.Delay(10); - Assert.True(work.ExecutionTime > TimeSpan.Zero); + Assert.True(work.LastExecutionTime > TimeSpan.Zero); } [Fact]