Implement media retry functionality and enhance error handling
ci / build-backend (push) Successful in 1m18s
ci / build-frontend (push) Failing after 15s
ci / tests (push) Skipped
ci / sonar (push) Skipped

Added endpoints for retrying failed media processing, allowing users to requeue media assets that encountered errors. Introduced error messages for scenarios where a media asset cannot be retried due to its status. Updated the MaintenanceBackgroundService to remove orphaned episodes and recompute group statistics, ensuring data integrity. Enhanced the frontend to support retry actions, including bulk retry options for failed media. Updated localization strings to reflect new features in both English and Russian.
This commit is contained in:
Leonid Pershin
2026-07-31 03:58:01 +03:00
parent 789357481d
commit 7163a0b937
16 changed files with 594 additions and 52 deletions
@@ -10,6 +10,7 @@ using TeleWave.Application.Media.ListMedia;
using TeleWave.Application.Media.ManualInbox;
using TeleWave.Application.Media.MovieImport;
using TeleWave.Application.Media.Register;
using TeleWave.Application.Media.Retry;
using TeleWave.Application.Media.Stats;
using TeleWave.Domain.Media;
using TeleWave.Infrastructure.Identity;
@@ -30,6 +31,10 @@ public static class MediaEndpoints
admin.MapGet("/stats", Stats).Produces<MediaStatsDto>();
admin.MapDelete("/{id:guid}", Delete).Produces(StatusCodes.Status204NoContent);
// Перезапуск упавшей обработки: файл на месте, повторить нарезку — обычное дело.
admin.MapPost("/{id:guid}/retry", Retry).Produces<RetryMediaResultDto>();
admin.MapPost("/retry-failed", RetryFailed).Produces<RetryMediaResultDto>();
// Ручной inbox: сканером не разбирается — файлы выбирает админ и сразу указывает шоу.
admin.MapGet("/manual", ListManual).Produces<ManualInboxListDto>();
admin.MapPost("/manual/import", ImportManual).Produces<ImportManualInboxResultDto>();
@@ -48,6 +53,25 @@ public static class MediaEndpoints
return app;
}
private static async Task<IResult> Retry(
Guid id,
ISender sender,
CancellationToken cancellationToken
)
{
var result = await sender.Send(new RetryMediaCommand(id), cancellationToken);
return result.ToHttpResult();
}
private static async Task<IResult> RetryFailed(
ISender sender,
CancellationToken cancellationToken
)
{
var result = await sender.Send(new RetryMediaCommand(), cancellationToken);
return result.ToHttpResult();
}
/// <summary>
/// Потоковая загрузка: тело запроса — сырые байты файла, имя передаётся в query «fileName».
/// Файл стримится на диск без буферизации в память, затем регистрируется и уходит в обработку.