Update configuration and enhance media processing: add stream token TTL and timeout settings in .env.example, improve error handling in media endpoints, and refactor command handlers for asynchronous operations. Update documentation to reflect current application state and features.
build / backend (push) Successful in 2m19s
build / frontend (push) Successful in 53s
tests / backend-tests (push) Successful in 2m27s

This commit is contained in:
Leonid Pershin
2026-07-25 23:14:55 +03:00
parent a261e261f0
commit 6c18a9da79
42 changed files with 387 additions and 98 deletions
@@ -26,7 +26,8 @@ public sealed class ClearBumperTemplateAudioCommandHandler(
return Result.Failure(ChannelErrors.BumperTemplateNotFound);
template.ClearAudio();
storage.DeleteAudio(command.TemplateId);
await dbContext.SaveChangesAsync(cancellationToken);
await storage.DeleteAudioAsync(command.TemplateId, cancellationToken);
return Result.Success();
}
}
@@ -28,7 +28,8 @@ public sealed class RemoveBumperTemplateCommandHandler(
return Result.Failure(ChannelErrors.CannotRemoveDefaultBumperTemplate);
channel.RemoveBumperTemplate(command.TemplateId);
storage.DeleteTemplate(command.TemplateId);
await dbContext.SaveChangesAsync(cancellationToken);
await storage.DeleteTemplateAsync(command.TemplateId, cancellationToken);
return Result.Success();
}
}
@@ -5,6 +5,7 @@ namespace TeleWave.Application.Broadcast.Bumpers;
/// <summary>
/// Синхронно рендерит примеры всех подблоков блока (с примерными названиями шоу). Каждый подблок —
/// в свой ассет-превью (id детерминирован по подблоку). БД не меняет — read-side генерация артефактов.
/// в свой ассет-превью (id детерминирован по подблоку). БД не меняет, но пишет артефакты на диск —
/// поэтому это команда (действие с побочным эффектом), а не запрос.
/// </summary>
public sealed record RenderBumperPreviewQuery(Guid ChannelId, Guid TemplateId) : IQuery<Result>;
public sealed record RenderBumperPreviewCommand(Guid ChannelId, Guid TemplateId) : ICommand<Result>;
@@ -8,14 +8,14 @@ using TeleWave.Domain.Broadcast;
namespace TeleWave.Application.Broadcast.Bumpers;
public sealed class RenderBumperPreviewQueryHandler(
public sealed class RenderBumperPreviewCommandHandler(
IAppDbContext dbContext,
IBumperRenderer renderer,
IBumperTemplateStorage storage,
IImageStore imageStore,
IOptions<BumperOptions> bumperOptions,
IOptions<StreamingOptions> streamingOptions
) : IQueryHandler<RenderBumperPreviewQuery, Result>
) : ICommandHandler<RenderBumperPreviewCommand, Result>
{
private readonly BumperOptions _bumper = bumperOptions.Value;
private readonly int _segmentSeconds = Math.Max(1, streamingOptions.Value.SegmentSeconds);
@@ -24,7 +24,7 @@ public sealed class RenderBumperPreviewQueryHandler(
private const int DefaultBumperDurationSeconds = 8;
public async Task<Result> Handle(
RenderBumperPreviewQuery query,
RenderBumperPreviewCommand query,
CancellationToken cancellationToken
)
{
@@ -50,6 +50,12 @@ public sealed class ScheduleGenerator(
if (channel is null || !channel.IsEnabled)
return -1;
// Сериализуем генерацию одного канала: фоновый тик и ручная перегенерация не должны читать
// одну точку продолжения и оба дописывать хвост (иначе дубли/перекрытия записей). Advisory-lock
// держится до коммита/отката транзакции ниже; при сбое рендера заставок весь прогон откатится.
await using var transaction = await dbContext.BeginTransactionAsync(cancellationToken);
await dbContext.AcquireChannelLockAsync(channelId, cancellationToken);
var horizonEnd = now.AddDays(_options.HorizonDays);
// Чистим прошлое сверх окна ретеншна.
@@ -77,6 +83,7 @@ public sealed class ScheduleGenerator(
if (startTime >= horizonEnd)
{
await dbContext.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return 0;
}
@@ -130,6 +137,7 @@ public sealed class ScheduleGenerator(
channel.SetNextBumperIndex(result.NextBumperIndex);
await dbContext.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return added;
}