using System; using System.Diagnostics; namespace AsbCloudApp.Data { /// /// Информация о фоновой работе /// public class BackgroundWorkDto { /// /// Идентификатор работы. Должен быть уникальным. Используется в логах и передается в колбэки. /// 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; } /// /// ctor /// /// 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[{100*progress:#}%]: {newState}"); } /// /// Обновления состояния при успешном завершении работы /// protected void SetStatusComplete() { 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}"); } } }