feat(api, core, dal, domain): В таблицу Tasks добавлено поле процент выполнения, так же добавлено это поле в response - статус формирования отчета. Создан интерфейс для отслеживания прогресса IProgressAsync. Из сервиса WorkloadService исключен ITaskManagementService.

This commit is contained in:
Mikhail Trubnikov
2026-05-20 14:26:25 +10:00
parent 8f61bbb73e
commit 68808e761b
17 changed files with 4160 additions and 41 deletions

View File

@@ -114,6 +114,10 @@ namespace PARR.Core.Services.TaskServices.Handlers
task.StatusCode = TaskItemStatusEnum.Processing;
task.DateModified = DateTimeOffset.UtcNow;
// Ставим процент 0
task.ProgressPercent = 0;
await taskRepository.UpdateProgressAsync(task.Id, 0);
return true;
}
@@ -129,7 +133,7 @@ namespace PARR.Core.Services.TaskServices.Handlers
/// <param name="task"></param>
/// <param name="result"></param>
/// <returns></returns>
private async System.Threading.Tasks.Task HandleSuccessAsync(TaskItem task, HandlerResult result)
private async Task HandleSuccessAsync(TaskItem task, HandlerResult result)
{
logger.LogInformation("Задача {TaskId} успешно выполнена", task.Id);
@@ -137,6 +141,9 @@ namespace PARR.Core.Services.TaskServices.Handlers
task.ProcessedAt = DateTimeOffset.UtcNow;
task.DateModified = DateTimeOffset.UtcNow;
// Ставим 100%
task.ProgressPercent = 100;
//todo: если есть результат, его можно сохранить, если надо
if (!string.IsNullOrEmpty(result.ResultData))
{
@@ -158,8 +165,19 @@ namespace PARR.Core.Services.TaskServices.Handlers
/// <param name="task"></param>
/// <param name="ex"></param>
/// <returns></returns>
private async System.Threading.Tasks.Task HandleErrorAsync(TaskItem task, Exception? ex)
private async Task HandleErrorAsync(TaskItem task, Exception? ex)
{
// задача в БД, у которой можно получить актуальный процент прогресса
var taskInDb = await taskRepository.Get()
.AsNoTracking()
.FirstOrDefaultAsync(t=>t.Id==task.Id);
if (taskInDb != null)
{
//так как в БД мы обновлям атомарно прогресс, то пришедший нам task не знает фактическое значение прогресса
task.ProgressPercent = taskInDb.ProgressPercent;
}
var attemptNumber = task.RetryCount + 1;
var errorMessage = ex?.Message ?? "Неизвестная ошибка";
var stackTrace = ex?.StackTrace;
@@ -219,7 +237,7 @@ namespace PARR.Core.Services.TaskServices.Handlers
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
protected virtual async System.Threading.Tasks.Task ScheduleRetryAsync(TaskItem task)
protected virtual async Task ScheduleRetryAsync(TaskItem task)
{
// Здесь нужна интеграция с ITaskQueueService
// Для этого можно использовать событие или callback
@@ -254,7 +272,7 @@ namespace PARR.Core.Services.TaskServices.Handlers
/// <param name="task"></param>
/// <param name="result"></param>
/// <returns></returns>
protected virtual System.Threading.Tasks.Task OnSuccessAsync(TaskItem task, HandlerResult result) => System.Threading.Tasks.Task.CompletedTask;
protected virtual Task OnSuccessAsync(TaskItem task, HandlerResult result) => System.Threading.Tasks.Task.CompletedTask;
/// <summary>
@@ -264,7 +282,43 @@ namespace PARR.Core.Services.TaskServices.Handlers
/// <param name="ex"></param>
/// <param name="attemptNumber"></param>
/// <returns></returns>
protected virtual System.Threading.Tasks.Task OnErrorAsync(TaskItem task, Exception? ex, int attemptNumber) => System.Threading.Tasks.Task.CompletedTask;
protected virtual Task OnErrorAsync(TaskItem task, Exception? ex, int attemptNumber) => System.Threading.Tasks.Task.CompletedTask;
/// <summary>
/// Обновляет процент выполнения задачи.
/// Обновлять процент не чаще 1 раза в 5 сек.
/// Вызывается из конкретного хендлера при желании показать прогресс.
/// </summary>
/// <param name="taskId">Id задачи</param>
/// <param name="percent">Процент (0-100). Значения >100 будут ограничены до 100.</param>
/// <returns></returns>
protected async Task UpdateProgressAsync(Guid taskId, int percent)
{
if (percent < 0)
{
logger.LogWarning("Попытка установить отрицательный прогресс {Percent} для задачи {TaskId}", percent, taskId);
percent = 0;
}
else if (percent > 100)
{
logger.LogWarning("Прогресс {Percent} для задачи {TaskId} превысил 100%. Записываем 100.", percent, taskId);
percent = 100;
}
// Обновляем в БД
var affectedRows = await taskRepository.UpdateProgressAsync(taskId, percent);
if (affectedRows == 0)
{
// Задача не найдена или уже завершена — не считаем ошибкой
logger.LogDebug("Не удалось обновить прогресс задачи {TaskId} (возможно, уже завершена)", taskId);
}
else
{
logger.LogDebug("Прогресс задачи {TaskId} обновлен: {Percent}%", taskId, percent);
}
}
}