diff --git a/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs b/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs index 924dd7f..c84cc8c 100644 --- a/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs +++ b/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs @@ -12,9 +12,14 @@ using Musify.Domain.Entities; namespace Musify.Application.PlayLists.Handlers { - public class CreatePlayListCommandHandler(IEventBus eventBus, IDatabase database, IStorageService storageHandler, - ILogger logger, ApplicationStorageConfiguration storageConfiguration, PlayListConfiguration playListConfiguration) - : ICommandHandler> + public class CreatePlayListCommandHandler( + IEventBus eventBus, + IDatabase database, + IStorageService storageService, + ILogger logger, + ApplicationStorageConfiguration storageConfiguration, + PlayListConfiguration playListConfiguration) + : ICommandHandler> { public async ValueTask> Handle(CreatePlayListCommand request, CancellationToken cancellationToken) { @@ -25,7 +30,8 @@ namespace Musify.Application.PlayLists.Handlers return Result.NotFound($"User {request.UserId} not found"); } - var playListEntity = CreatePlayListCommand.ToEntity(request, + var playList = CreatePlayListCommand.ToEntity( + request, playListConfiguration.Routes.PresetOriginalPicture, playListConfiguration.Routes.PresetSmallPicture, playListConfiguration.Routes.PresetMediumPicture, @@ -33,70 +39,57 @@ namespace Musify.Application.PlayLists.Handlers if (request.Picture is not null) { - var uploadResult = await SetPicture(playListEntity, request.Picture, cancellationToken); + var uploadResult = await UploadPictureAsync(playList, request.Picture, cancellationToken); if (!uploadResult.IsSuccess) return uploadResult; - - var publishResult = await PublishUpdateEvent(playListEntity, cancellationToken); - if (!publishResult.IsSuccess) - { - await RollbackPicture(playListEntity, cancellationToken); - return publishResult; - } } try { - await database.PlayLists.AddAsync(playListEntity, cancellationToken); + await database.PlayLists.AddAsync(playList, cancellationToken); await database.SaveChangesAsync(cancellationToken); } catch (Exception exception) { - await RollbackPicture(playListEntity, cancellationToken); - logger.LogError(exception, "Failed to create playlist for user {UserId}", request.UserId); + logger.LogError(exception, "Failed to save playlist for user {UserId}", request.UserId); + await RollbackAllPicturesAsync(playList, cancellationToken); return Result.Error($"Failed to create playlist for user {request.UserId}"); } - logger.LogInformation("Created playlist {PlayListId} for user {UserId}", playListEntity.Id, request.UserId); - return Result.Created(PlayListResponse.FromEntity(playListEntity)); + if (request.Picture is not null) + { + var publishResult = await PublishPictureUpdateEventAsync(playList, cancellationToken); + if (!publishResult.IsSuccess) + return publishResult; + } + + logger.LogInformation("Created playlist {PlayListId} for user {UserId}", playList.Id, request.UserId); + return Result.Created(PlayListResponse.FromEntity(playList)); } - async Task RollbackPicture(PlayList playList, CancellationToken cancellationToken) - { - try - { - await storageHandler.RemoveFileAsync(storageConfiguration.Bucket, - Path.Combine(playListConfiguration.Routes.OriginalPicturesPath, playList.OriginalPictureName), cancellationToken); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to rollback picture upload for playlist {PlayListId}", playList.Id); - } - } - - async Task SetPicture(PlayList playList, IFileData picture, CancellationToken cancellationToken) + async Task UploadPictureAsync(PlayList playList, IFileData picture, CancellationToken cancellationToken) { var pictureName = Guid.NewGuid() + picture.FileType; var pictureKey = Path.Combine(playListConfiguration.Routes.OriginalPicturesPath, pictureName); try { - await storageHandler.UploadFileAsync(picture.FileStream, picture.ContentType, storageConfiguration.Bucket, pictureKey, cancellationToken); + await storageService.UploadFileAsync(picture.FileStream, picture.ContentType, storageConfiguration.Bucket, pictureKey, cancellationToken); + playList.OriginalPictureName = pictureName; + return Result.Success(); } - catch + catch (Exception exception) { - return Result.Error($"An error occurred while uploading picture for playlist {playList.Id} to storage."); + logger.LogError(exception, "Failed to upload picture for playlist {PlayListId}", playList.Id); + return Result.Error($"Failed to upload picture for playlist {playList.Id}"); } - - playList.OriginalPictureName = pictureName; - return Result.Success(); } - async Task PublishUpdateEvent(PlayList playList, CancellationToken cancellationToken) + async Task PublishPictureUpdateEventAsync(PlayList playList, CancellationToken cancellationToken) { try { - await eventBus.PublishAsync(new UpdatePlayListPictureEvent( + var updateEvent = new UpdatePlayListPictureEvent( playList.Id, storageConfiguration.Bucket, Path.Combine(playListConfiguration.Routes.OriginalPicturesPath, playList.OriginalPictureName), @@ -111,14 +104,32 @@ namespace Musify.Application.PlayLists.Handlers new ImageSize( playListConfiguration.Routes.LargePicturesPath, playListConfiguration.PicturesSizes.LargePictureWidth, - playListConfiguration.PicturesSizes.LargePictureHeight)), - cancellationToken); + playListConfiguration.PicturesSizes.LargePictureHeight)); + + await eventBus.PublishAsync(updateEvent, cancellationToken); return Result.Success(); } catch (Exception exception) { - logger.LogError(exception, "Failed to publish playlist picture update event for playlist {PlayListId}", playList.Id); - return Result.Error($"Failed to publish playlist {playList.Id} picture update event"); + logger.LogError(exception, "Failed to publish picture update event for playlist {PlayListId}", playList.Id); + return Result.Error($"Failed to publish picture update event for playlist {playList.Id}"); + } + } + + async Task RollbackAllPicturesAsync(PlayList playList, CancellationToken cancellationToken) + { + if (string.IsNullOrEmpty(playList.OriginalPictureName)) + return; + + var originalPicturePath = Path.Combine(playListConfiguration.Routes.OriginalPicturesPath, playList.OriginalPictureName); + + try + { + await storageService.RemoveFileAsync(storageConfiguration.Bucket, originalPicturePath, cancellationToken); + } + catch (Exception exception) + { + logger.LogError(exception, "Failed to rollback picture upload for playlist {PlayListId}", playList.Id); } } }