Files
TeleWave/backend/src/TeleWave.Application/Media/Register/RegisterMediaAssetCommandHandler.cs
T

55 lines
2.3 KiB
C#

using LiteCqrs;
using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;
using TeleWave.Domain.Media;
namespace TeleWave.Application.Media.Register;
public sealed class RegisterMediaAssetCommandHandler(IAppDbContext dbContext, IMediaStorage storage)
: ICommandHandler<RegisterMediaAssetCommand, Result<Guid>>
{
public async Task<Result<Guid>> Handle(
RegisterMediaAssetCommand command,
CancellationToken cancellationToken
)
{
// Дедуп по имени: тот же файл уже в библиотеке (кроме проваленных — их разрешаем перезалить).
var duplicate = await dbContext.MediaAssets.AnyAsync(
x =>
x.OriginalFileName == command.OriginalFileName
&& x.Status != MediaAssetStatus.Failed,
cancellationToken
);
if (duplicate)
return Result.Failure<Guid>(MediaErrors.DuplicateFileName);
var extension = Path.GetExtension(command.OriginalFileName).ToLowerInvariant();
var asset = MediaAsset.Register(command.OriginalFileName, extension, command.Source);
// Сначала фиксируем ассет в БД, затем переносим файл в originals/. Если перенос не удался —
// откатываем регистрацию, чтобы не оставить orphan (либо есть и строка БД, и файл, либо нет ни
// того, ни другого). Обратный порядок оставлял бы перемещённый файл без строки БД при сбое save.
dbContext.MediaAssets.Add(asset);
await dbContext.SaveChangesAsync(cancellationToken);
try
{
await storage.PromoteToOriginalAsync(
command.Source,
command.SourceToken,
asset.Id,
extension,
cancellationToken
);
}
catch
{
dbContext.MediaAssets.Remove(asset);
await dbContext.SaveChangesAsync(cancellationToken);
throw;
}
return Result.Success(asset.Id);
}
}