diff --git a/AsbCloudInfrastructure/Background/BackgroudWorkDto.cs b/AsbCloudInfrastructure/Background/BackgroudWorkDto.cs
new file mode 100644
index 00000000..873217eb
--- /dev/null
+++ b/AsbCloudInfrastructure/Background/BackgroudWorkDto.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Diagnostics;
+
+namespace AsbCloudInfrastructure.Background
+{
+ public class BackgroudWorkDto
+ {
+ ///
+ /// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки.
+ ///
+ public string Id { get; init; } = null!;
+
+ public class CurrentStateInfo
+ {
+ private string state = "start";
+
+ ///
+ /// Время последнего запуска
+ ///
+ public DateTime Start { get; } = DateTime.Now;
+
+ ///
+ /// Текущее время выполнения
+ ///
+ public TimeSpan ExecutionTime => DateTime.Now - Start;
+
+ ///
+ /// Текстовое описание того, что происходит в задаче.
+ ///
+ public string State
+ {
+ get => state;
+ internal set
+ {
+ state = value;
+ StateUpdate = DateTime.Now;
+ }
+ }
+
+ public double Progress { get; internal set; } = 0;
+
+ ///
+ /// Время последнего запуска
+ ///
+ public DateTime StateUpdate { get; private set; } = DateTime.Now;
+ }
+
+ public class LastErrorInfo: LastCompleteInfo
+ {
+ public LastErrorInfo(CurrentStateInfo state, string errorText)
+ : base(state)
+ {
+ ErrorText = errorText;
+ }
+
+ ///
+ /// Последняя ошибка
+ ///
+ public string ErrorText { get; init; } = null!;
+ }
+
+ public class LastCompleteInfo
+ {
+ ///
+ /// Дата запуска
+ ///
+ public DateTime Start {get; init;}
+
+ ///
+ /// Дата завершения
+ ///
+ public DateTime End { get; init; }
+
+ ///
+ /// Продолжительность последнего выполнения
+ ///
+ public TimeSpan ExecutionTime => End - Start;
+
+ ///
+ /// Состояние на момент завершения
+ ///
+ public string State { get; init; }
+
+ public LastCompleteInfo(CurrentStateInfo state)
+ {
+ Start = state.Start;
+ End = DateTime.Now;
+ State = state.State;
+ }
+ }
+
+ ///
+ /// Текущее состояние
+ ///
+ public CurrentStateInfo? CurrentState { get; private set; }
+
+ ///
+ /// Последняя ошибка
+ ///
+ public LastErrorInfo? LastError { get; private set; }
+
+ ///
+ /// Последняя завершенная
+ ///
+ public LastCompleteInfo? LastComplete { get; private set; }
+
+ ///
+ /// Кол-во запусков
+ ///
+ public int CountStart { get; private set; }
+
+ ///
+ /// Кол-во завершений
+ ///
+ public int CountComplete { get; private set; }
+
+ ///
+ /// Кол-во ошибок
+ ///
+ public int CountErrors { get; private set; }
+
+ ///
+ /// Максимально допустимое время выполнения работы
+ ///
+ public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(1);
+
+ private string WorkNameForTrace => $"Backgroud work:\"{Id}\"";
+
+ protected void SetStatusStart()
+ {
+ CurrentState = new();
+ CountStart++;
+ Trace.TraceInformation($"{WorkNameForTrace} state: starting");
+ }
+
+ protected void UpdateStatus(string newState, double? progress)
+ {
+ if (CurrentState is null)
+ return;
+
+ CurrentState.State = newState;
+ if (progress.HasValue)
+ CurrentState.Progress = progress.Value;
+
+ Trace.TraceInformation($"{WorkNameForTrace} state: {newState}");
+ }
+
+ protected void SetStatusComplete(System.Threading.Tasks.TaskStatus status)
+ {
+ if (CurrentState is null)
+ return;
+
+ LastComplete = new (CurrentState);
+ CurrentState = null;
+ CountComplete++;
+ Trace.TraceInformation($"{WorkNameForTrace} state: completed");
+ }
+
+ protected void SetLastError(string errorMessage)
+ {
+ if (CurrentState is null)
+ return;
+
+ LastError = new LastErrorInfo(CurrentState, errorMessage);
+ CurrentState = null;
+ CountErrors++;
+ Trace.TraceError($"{WorkNameForTrace} throw exception[{CountErrors}]: {errorMessage}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Background/BackgroundWorker.cs b/AsbCloudInfrastructure/Background/BackgroundWorker.cs
index 4ba3d535..fad61edf 100644
--- a/AsbCloudInfrastructure/Background/BackgroundWorker.cs
+++ b/AsbCloudInfrastructure/Background/BackgroundWorker.cs
@@ -15,7 +15,7 @@ namespace AsbCloudInfrastructure.Background
private static readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10);
private static readonly TimeSpan minDelay = TimeSpan.FromSeconds(2);
private readonly IServiceProvider serviceProvider;
- private readonly WorkQueue workQueue = new WorkQueue();
+ private readonly WorkStore workQueue = new WorkStore();
public string? CurrentWorkId;
public BackgroundWorker(IServiceProvider serviceProvider)
diff --git a/AsbCloudInfrastructure/Background/OrderedList.cs b/AsbCloudInfrastructure/Background/OrderedList.cs
new file mode 100644
index 00000000..1f583a82
--- /dev/null
+++ b/AsbCloudInfrastructure/Background/OrderedList.cs
@@ -0,0 +1,41 @@
+using System.Linq;
+
+namespace System.Collections.Generic
+{
+ public class OrderedList: IEnumerable, ICollection
+ where T : notnull
+ {
+ private readonly List list = new List();
+
+ private readonly Func keySelector;
+ private readonly bool isDescending = false;
+
+ private IOrderedEnumerable OrdredList => isDescending
+ ? list.OrderByDescending(keySelector)
+ : list.OrderBy(keySelector);
+
+ public int Count => list.Count;
+
+ public bool IsReadOnly => false;
+
+ public OrderedList(Func keySelector, bool isDescending = false)
+ {
+ this.keySelector = keySelector;
+ this.isDescending = isDescending;
+ }
+
+ public void Add(T item) => list.Add(item);
+
+ public void Clear()=> list.Clear();
+
+ public bool Contains(T item)=> list.Contains(item);
+
+ public void CopyTo(T[] array, int arrayIndex)=> list.CopyTo(array, arrayIndex);
+
+ public bool Remove(T item)=> list.Remove(item);
+
+ public IEnumerator GetEnumerator() => OrdredList.GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+}
diff --git a/AsbCloudInfrastructure/Background/WorkBase.cs b/AsbCloudInfrastructure/Background/WorkBase.cs
index ef238a85..e1b83053 100644
--- a/AsbCloudInfrastructure/Background/WorkBase.cs
+++ b/AsbCloudInfrastructure/Background/WorkBase.cs
@@ -1,6 +1,4 @@
using System;
-using System.Diagnostics;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -10,14 +8,23 @@ namespace AsbCloudInfrastructure.Background
/// Класс разовой работы.
/// Разовая работа приоритетнее периодической.
///
- public class WorkBase
+ public class WorkBase : BackgroudWorkDto
{
- ///
- /// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки.
- ///
- public string Id { get; }
+ internal Func, CancellationToken, Task> ActionAsync { get; }
///
+ /// Делегат обработки ошибки.
+ /// Не должен выполняться долго.
+ ///
+ public Func? OnErrorAsync { get; set; }
+
+ public TimeSpan OnErrorHandlerTimeout { get; set; } = TimeSpan.FromSeconds(5);
+
+ ///
+ /// Базовая работа
+ ///
+ ///
+ ///
/// Делегат работы.
///
/// Параметры:
@@ -31,138 +38,50 @@ namespace AsbCloudInfrastructure.Background
/// Поставщик сервисов
///
/// -
+ /// Action<string, double?>
+ /// on progress callback. String - new state text. double? - optional progress 0-100%.
+ ///
+ /// -
/// CancellationToken
/// Токен отмены задачи
///
///
///
- ///
- internal Func ActionAsync { get; }
-
- ///
- /// Делегат обработки ошибки.
- /// Не должен выполняться долго.
- ///
- public Func? OnErrorAsync { get; set; }
-
- ///
- /// максимально допустимое время выполнения работы
- ///
- public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(1);
-
- ///
- /// Продолжительность последнего выполнения
- ///
- public TimeSpan? LastExecutionTime { get; private set; }
-
- ///
- /// Текущее время выполнения
- ///
- public TimeSpan? CurrentExecutionTime => CurrentStart.HasValue
- ? DateTime.Now - CurrentStart.Value
- : null;
-
- ///
- /// Время последнего запуска
- ///
- 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)
+ ///
+ public WorkBase(string id, Func, CancellationToken, Task> actionAsync)
{
Id = id;
ActionAsync = actionAsync;
}
- public async Task Start(IServiceProvider services, CancellationToken token)
+ ///
+ /// Запустить работу
+ ///
+ ///
+ ///
+ /// True - susess, False = Fail
+ public async Task Start(IServiceProvider services, CancellationToken token)
{
- CurrentStart = DateTime.Now;
- LastStart = DateTime.Now;
+ SetStatusStart();
try
{
- SetStatus(" start");
- var task = ActionAsync(Id, services, token);
+ var task = ActionAsync(Id, services, UpdateStatus, token);
await task.WaitAsync(Timeout, token);
- LastComplete = DateTime.Now;
- CountComplete++;
- SetStatus($" {task.Status}. ExecutionTime: {CurrentExecutionTime:hh\\:mm\\:ss\\.fff}");
+ SetStatusComplete(task.Status);
+ return true;
}
catch (Exception exception)
{
- SetError(exception.Message);
+ SetLastError(exception.Message);
if (OnErrorAsync is not null)
{
var task = Task.Run(
async () => await OnErrorAsync(Id, exception, token),
token);
- await task.WaitAsync(Timeout, token);
+ await task.WaitAsync(OnErrorHandlerTimeout, 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}");
+ return false;
}
}
}
diff --git a/AsbCloudInfrastructure/Background/WorkPeriodic.cs b/AsbCloudInfrastructure/Background/WorkPeriodic.cs
index 5c2b0e23..71d580ed 100644
--- a/AsbCloudInfrastructure/Background/WorkPeriodic.cs
+++ b/AsbCloudInfrastructure/Background/WorkPeriodic.cs
@@ -18,7 +18,16 @@ namespace AsbCloudInfrastructure.Background
///
/// Время следующего запуска
///
- public DateTime NextStart => LastStart??DateTime.MinValue + Period;
+ public DateTime NextStart
+ {
+ get
+ {
+ var lastStart = LastComplete?.Start ?? DateTime.MinValue;
+ if (LastError?.Start > lastStart)
+ lastStart = LastError.Start;
+ return lastStart + Period;
+ }
+ }
///
/// Класс периодической работы
@@ -26,7 +35,7 @@ namespace AsbCloudInfrastructure.Background
/// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки
/// Делегат работы
/// Период выполнения задачи
- public WorkPeriodic(string id, Func actionAsync, TimeSpan period)
+ public WorkPeriodic(string id, Func, CancellationToken, Task> actionAsync, TimeSpan period)
: base(id, actionAsync)
{
Period = period;
diff --git a/AsbCloudInfrastructure/Background/WorkQueue.cs b/AsbCloudInfrastructure/Background/WorkStore.cs
similarity index 70%
rename from AsbCloudInfrastructure/Background/WorkQueue.cs
rename to AsbCloudInfrastructure/Background/WorkStore.cs
index e925916b..590ad8a6 100644
--- a/AsbCloudInfrastructure/Background/WorkQueue.cs
+++ b/AsbCloudInfrastructure/Background/WorkStore.cs
@@ -10,11 +10,25 @@ namespace AsbCloudInfrastructure.Background
///
/// Не периодические задачи будут возвращаться первыми, как самые приоритетные.
///
- class WorkQueue
+ class WorkStore
{
- private Queue Primary = new(8);
private readonly List Periodic = new(8);
+ ///
+ /// Работы выполняемые один раз
+ ///
+ public Queue RunOnceQueue { get; } = new(8);
+
+ ///
+ /// Работы выполняемые периодически
+ ///
+ public IOrderedEnumerable Periodics => Periodic.OrderBy(work => work.NextStart);
+
+ ///
+ /// Завершывшиеся с ошибкой
+ ///
+ public CyclycArray Falled { get; } = new(16);
+
///
/// Добавление работы.
///
@@ -25,8 +39,8 @@ namespace AsbCloudInfrastructure.Background
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 (Primary.Any(w => w.Id == work.Id))
+ // throw new ArgumentException("work.Id is not unique", nameof(work));
if (work is WorkPeriodic workPeriodic)
{
@@ -34,7 +48,7 @@ namespace AsbCloudInfrastructure.Background
return;
}
- Primary.Enqueue(work);
+ //Primary.Enqueue(work);
}
///
@@ -51,19 +65,19 @@ namespace AsbCloudInfrastructure.Background
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;
- }
+ //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);
+ var result = false;//Periodic.Any(w => w.Id == id) || Primary.Any(w => w.Id == id);
return result;
}
@@ -82,8 +96,8 @@ namespace AsbCloudInfrastructure.Background
///
public WorkBase? Pop()
{
- if (Primary.Any())
- return Primary.Dequeue();
+ //if (Primary.Any())
+ // return Primary.Dequeue();
var work = GetNextPeriodic();
if (work is null || work.NextStart > DateTime.Now)
diff --git a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionWorkFactory.cs b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionWorkFactory.cs
index da171f13..350ad6b7 100644
--- a/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionWorkFactory.cs
+++ b/AsbCloudInfrastructure/Services/DetectOperations/OperationDetectionWorkFactory.cs
@@ -46,7 +46,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
}
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
- private static async Task WorkAction(string _, IServiceProvider serviceProvider, CancellationToken token)
+ private static async Task WorkAction(string _, IServiceProvider serviceProvider, Action onProgress, CancellationToken token)
{
using var db = serviceProvider.GetRequiredService();
@@ -75,10 +75,14 @@ namespace AsbCloudInfrastructure.Services.DetectOperations
});
var affected = 0;
+ var count = joinedlastDetectedDates.Count();
+ var i = 0;
foreach (var item in joinedlastDetectedDates)
{
var stopwatch = Stopwatch.StartNew();
- var newOperations = await DetectOperationsAsync(item.IdTelemetry, item.LastDate ?? DateTimeOffset.MinValue, db, token);
+ var startDate = item.LastDate ?? DateTimeOffset.MinValue;
+ onProgress($"start detecting telemetry: {item.IdTelemetry} from {startDate}", i++ / count);
+ var newOperations = await DetectOperationsAsync(item.IdTelemetry, startDate, db, token);
stopwatch.Stop();
if (newOperations.Any())
{
diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs
index 9dc20155..cf41ab7c 100644
--- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs
+++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs
@@ -519,11 +519,12 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.pdf";
var convertedFilesDir = Path.Combine(Path.GetTempPath(), "drillingProgram", $"{well.Cluster}_{well.Caption}");
var tempResultFilePath = Path.Combine(convertedFilesDir, resultFileName);
- var workAction = async (string workId, IServiceProvider serviceProvider, CancellationToken token) =>
+ var workAction = async (string workId, IServiceProvider serviceProvider, Action onProgress, CancellationToken token) =>
{
var context = serviceProvider.GetRequiredService();
var fileService = serviceProvider.GetRequiredService();
var files = state.Parts.Select(p => fileService.GetUrl(p.File!));
+ onProgress($"Start converting {files.Count()} files to PDF.", null);
await ConvertToPdf.GetConverteAndMergedFileAsync(files, tempResultFilePath, convertedFilesDir, token);
await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token);
};
diff --git a/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs
index 26eed2be..412a4354 100644
--- a/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs
+++ b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs
@@ -10,6 +10,7 @@ using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services.Notifications;
using AsbCloudInfrastructure.Background;
+using DocumentFormat.OpenXml.Presentation;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -70,9 +71,9 @@ namespace AsbCloudInfrastructure.Services.Email
return Task.WhenAll(tasks);
}
- private Func MakeEmailSendWorkAction(NotificationDto notification)
+ private Func, CancellationToken, Task> MakeEmailSendWorkAction(NotificationDto notification)
{
- return async (_, serviceProvider, token) =>
+ return async (_, serviceProvider, onProgress, token) =>
{
var notificationRepository = serviceProvider.GetRequiredService();
var userRepository = serviceProvider.GetRequiredService();
diff --git a/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs b/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs
index 7c875e70..6c4f94c1 100644
--- a/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs
+++ b/AsbCloudInfrastructure/Services/LimitingParameterBackgroundService.cs
@@ -28,7 +28,7 @@ namespace AsbCloudInfrastructure.Services
}
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
- private static async Task WorkAction(string _, IServiceProvider serviceProvider, CancellationToken token)
+ private static async Task WorkAction(string _, IServiceProvider serviceProvider, Action onProgress, CancellationToken token)
{
using var db = serviceProvider.GetRequiredService();
var lastDetectedDates = await db.LimitingParameter
@@ -55,8 +55,11 @@ namespace AsbCloudInfrastructure.Services
inner.SingleOrDefault()?.LastDate,
});
+ var count = telemetryLastDetectedDates.Count();
+ var i = 0;
foreach (var item in telemetryLastDetectedDates)
{
+ onProgress($"Start hanling telemetry: {item.IdTelemetry} from {item.LastDate}", i++/count);
var newLimitingParameters = await GetLimitingParameterAsync(item.IdTelemetry, item.LastDate ?? DateTimeOffset.MinValue, db, token);
if (newLimitingParameters?.Any() == true)
{
diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs
index eca8f84e..95851c74 100644
--- a/AsbCloudInfrastructure/Services/ReportService.cs
+++ b/AsbCloudInfrastructure/Services/ReportService.cs
@@ -51,7 +51,7 @@ namespace AsbCloudInfrastructure.Services
var workId = $"create report by wellid:{idWell} for userid:{idUser} requested at {DateTime.Now}";
- var workAction = async (string id, IServiceProvider serviceProvider, CancellationToken token) =>
+ var workAction = async (string id, IServiceProvider serviceProvider, Action onProgress, CancellationToken token) =>
{
using var context = serviceProvider.GetRequiredService();
var fileService = serviceProvider.GetRequiredService();
@@ -64,7 +64,9 @@ namespace AsbCloudInfrastructure.Services
generator.OnProgress += (s, e) =>
{
- progressHandler.Invoke(e.Adapt(), id);
+ var arg = e.Adapt();
+ onProgress(arg.Operation?? string.Empty, arg.Progress);
+ progressHandler.Invoke(arg, id);
};
generator.Make(reportFileName);
diff --git a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
index d1a7fea1..8868fc24 100644
--- a/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
+++ b/AsbCloudInfrastructure/Services/SAUB/TelemetryDataCache.cs
@@ -48,9 +48,9 @@ namespace AsbCloudInfrastructure.Services.SAUB
instance = new TelemetryDataCache();
var worker = provider.GetRequiredService();
var workId = $"Telemetry cache loading from DB {typeof(TEntity).Name}";
- var work = new WorkBase(workId, async (workId, provider, token) => {
+ var work = new WorkBase(workId, async (workId, provider, onProgress, token) => {
var db = provider.GetRequiredService();
- await instance.InitializeCacheFromDBAsync(db, token);
+ await instance.InitializeCacheFromDBAsync(db, onProgress, token);
});
worker.Push(work);
@@ -150,7 +150,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
return new DatesRangeDto { From = from.Value, To = to };
}
- private async Task InitializeCacheFromDBAsync(IAsbCloudDbContext db, CancellationToken token)
+ private async Task InitializeCacheFromDBAsync(IAsbCloudDbContext db, Action onProgress, CancellationToken token)
where TEntity : class, AsbCloudDb.Model.ITelemetryData
{
if (isLoading)
@@ -168,6 +168,8 @@ namespace AsbCloudInfrastructure.Services.SAUB
.Where(well => well.IdTelemetry != null)
.ToArrayAsync(token);
+ var count = wells.Count();
+ var i = 0;
foreach (Well well in wells)
{
var capacity = well.IdState == 1
@@ -176,7 +178,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
var idTelemetry = well.IdTelemetry!.Value;
var hoursOffset = well.Timezone.Hours;
-
+ // TODO: remove traces
System.Diagnostics.Trace.TraceInformation($"cache<{typeof(TDto).Name}>: Loading for well: {well.Cluster?.Caption}/{well.Caption} (capacity:{capacity}) idTelemetry:{idTelemetry}");
var cacheItem = await GetOrDefaultCacheDataFromDbAsync(db, idTelemetry, capacity, hoursOffset, token);
if(cacheItem is not null)
diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeCalcWorkFactory.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeCalcWorkFactory.cs
index d5b86803..bbbc1fb5 100644
--- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeCalcWorkFactory.cs
+++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeCalcWorkFactory.cs
@@ -36,7 +36,7 @@ namespace AsbCloudInfrastructure.Services.Subsystems
}
// TODO: Разделить этот акшн на более мелкие части И использовать telemetryServiceData<..> вместо прямого обращения к БД.
- private static async Task WorkAction(string _, IServiceProvider serviceProvider, CancellationToken token)
+ private static async Task WorkAction(string _, IServiceProvider serviceProvider, Action onProgress, CancellationToken token)
{
using var db = serviceProvider.GetRequiredService();
@@ -64,8 +64,11 @@ namespace AsbCloudInfrastructure.Services.Subsystems
inner.SingleOrDefault()?.LastDate,
});
+ var count = telemetryLastDetectedDates.Count();
+ var i = 0;
foreach (var item in telemetryLastDetectedDates)
{
+ onProgress($"Start hanling telemetry: {item.IdTelemetry} from {item.LastDate}", i++ / count);
var newOperationsSaub = await OperationTimeSaubAsync(item.IdTelemetry, item.LastDate ?? DateTimeOffset.MinValue, db, token);
if (newOperationsSaub?.Any() == true)
{
diff --git a/AsbCloudInfrastructure/Services/WellInfoService.cs b/AsbCloudInfrastructure/Services/WellInfoService.cs
index eea573cc..0d6951b2 100644
--- a/AsbCloudInfrastructure/Services/WellInfoService.cs
+++ b/AsbCloudInfrastructure/Services/WellInfoService.cs
@@ -62,7 +62,7 @@ namespace AsbCloudInfrastructure.Services
return workPeriodic;
}
- private static async Task WorkAction(string workName, IServiceProvider serviceProvider, CancellationToken token)
+ private static async Task WorkAction(string workName, IServiceProvider serviceProvider, Action onProgress, CancellationToken token)
{
var wellService = serviceProvider.GetRequiredService();
var operationsStatService = serviceProvider.GetRequiredService();
@@ -90,11 +90,12 @@ namespace AsbCloudInfrastructure.Services
var subsystemStat = await subsystemOperationTimeService
.GetStatByActiveWells(wellsIds, token);
-
+ var count = wells.Count();
+ var i = 0;
WellMapInfo = wells.Select(well => {
var wellMapInfo = well.Adapt();
wellMapInfo.IdState = well.IdState;
-
+ onProgress($"Start updating info by well({well.Id}): {well.Caption}", i++ / count);
double? currentDepth = null;
TelemetryDataSaubDto? lastSaubTelemetry = null;
diff --git a/AsbCloudInfrastructure/Startup.cs b/AsbCloudInfrastructure/Startup.cs
index c1c3cc8f..54d5d080 100644
--- a/AsbCloudInfrastructure/Startup.cs
+++ b/AsbCloudInfrastructure/Startup.cs
@@ -51,7 +51,7 @@ namespace AsbCloudInfrastructure
static WorkPeriodic MakeMemoryMonitoringWork()
{
var workId = "Memory monitoring";
- var workAction = (string _, IServiceProvider _, CancellationToken _) => {
+ var workAction = (string _, IServiceProvider _, Action _, 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}");
diff --git a/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs b/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs
index b418c0b5..9633eb1c 100644
--- a/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs
+++ b/AsbCloudWebApi/SignalR/Services/SignalRNotificationTransportService.cs
@@ -39,9 +39,9 @@ public class SignalRNotificationTransportService : INotificationTransportService
return Task.CompletedTask;
}
- private Func MakeSignalRSendWorkAction(IEnumerable notifications)
+ private Func, CancellationToken, Task> MakeSignalRSendWorkAction(IEnumerable notifications)
{
- return async (_, serviceProvider, cancellationToken) =>
+ return async (_, serviceProvider, onProgress, cancellationToken) =>
{
var notificationPublisher = serviceProvider.GetRequiredService();