From 076f048efe36a07846379d098b409ea8916714c3 Mon Sep 17 00:00:00 2001 From: XShine555 Date: Wed, 18 Mar 2026 10:52:00 +0100 Subject: [PATCH] Changes and fixes --- .../Contracts/Application/IPictureService.cs | 5 +- .../Commands/ResizePicture/ResizeCommand.cs | 3 + .../ResizePicture/ResizeCommandHandler.cs | 3 +- .../Pictures/Contracts/PictureResize.cs | 3 +- Application/Pictures/PictureService.cs | 6 +- .../CreatePlayListCommandHandler.cs | 13 +++- .../PlayLists/Contracts/PlayListResponse.cs | 2 +- .../GetPlayListByIdQueryHandler.cs | 8 +- .../GetPlayLists/GetPlayListsQueryHandler.cs | 9 +-- .../GetPlayListsByUserIdQueryHandler.cs | 9 +-- .../Consumers/ImageResizedConsumer.cs | 76 +++++++++++-------- Musify.Backend/Entities/EntityType.cs | 9 +++ Musify.Backend/Entities/Upload.cs | 6 ++ 13 files changed, 87 insertions(+), 65 deletions(-) create mode 100644 Musify.Backend/Entities/EntityType.cs diff --git a/Application/Contracts/Application/IPictureService.cs b/Application/Contracts/Application/IPictureService.cs index 5adba92..b8bab3a 100644 --- a/Application/Contracts/Application/IPictureService.cs +++ b/Application/Contracts/Application/IPictureService.cs @@ -1,11 +1,12 @@ using Ardalis.Result; using Musify.Application.Pictures.Contracts; +using Musify.Domain.Entities; namespace Musify.Application.Contracts.Application { public interface IPictureService { - Task> ResizePictureAsync(string keyName, string contentType, Stream pictureStream, PictureResize[] pictureResizes, - CancellationToken cancellationToken); + Task> ResizePictureAsync(EntityType entityType, Guid EntityId, string keyName, string contentType, Stream pictureStream, + PictureResize[] pictureResizes, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/Application/Pictures/Commands/ResizePicture/ResizeCommand.cs b/Application/Pictures/Commands/ResizePicture/ResizeCommand.cs index 628ad6d..707ed8d 100644 --- a/Application/Pictures/Commands/ResizePicture/ResizeCommand.cs +++ b/Application/Pictures/Commands/ResizePicture/ResizeCommand.cs @@ -1,10 +1,13 @@ using Ardalis.Result; using DispatchR.Abstractions.Send; using Musify.Application.Pictures.Contracts; +using Musify.Domain.Entities; namespace Musify.Application.Pictures.Commands.ResizePicture { public record ResizeCommand( + EntityType EntityType, + Guid EntityId, string KeyName, string ContentType, Stream PictureStream, diff --git a/Application/Pictures/Commands/ResizePicture/ResizeCommandHandler.cs b/Application/Pictures/Commands/ResizePicture/ResizeCommandHandler.cs index 95b61fd..bd61a9c 100644 --- a/Application/Pictures/Commands/ResizePicture/ResizeCommandHandler.cs +++ b/Application/Pictures/Commands/ResizePicture/ResizeCommandHandler.cs @@ -9,7 +9,8 @@ namespace Musify.Application.Pictures.Commands.ResizePicture { public async Task> Handle(ResizeCommand request, CancellationToken cancellationToken) { - var result = await pictureService.ResizePictureAsync(request.KeyName, request.ContentType, request.PictureStream, request.PictureResizes, cancellationToken); + var result = await pictureService.ResizePictureAsync(request.EntityType, request.EntityId, request.KeyName, request.ContentType, + request.PictureStream, request.PictureResizes, cancellationToken); return result; } diff --git a/Application/Pictures/Contracts/PictureResize.cs b/Application/Pictures/Contracts/PictureResize.cs index 44b79fa..f66021a 100644 --- a/Application/Pictures/Contracts/PictureResize.cs +++ b/Application/Pictures/Contracts/PictureResize.cs @@ -2,5 +2,6 @@ { public record PictureResize( int Width, - int Height); + int Height, + string SaveOnRoute); } \ No newline at end of file diff --git a/Application/Pictures/PictureService.cs b/Application/Pictures/PictureService.cs index 306131f..c061995 100644 --- a/Application/Pictures/PictureService.cs +++ b/Application/Pictures/PictureService.cs @@ -15,8 +15,8 @@ namespace Musify.Application.Pictures ILogger logger, StorageConfiguration storageConfiguration) : IPictureService { - public async Task> ResizePictureAsync(string keyName, string contentType, Stream pictureStream, PictureResize[] pictureResizes, - CancellationToken cancellationToken) + public async Task> ResizePictureAsync(EntityType entityType, Guid EntityId, string keyName, string contentType, Stream pictureStream, + PictureResize[] pictureResizes, CancellationToken cancellationToken) { var pictureId = Guid.NewGuid(); @@ -26,6 +26,8 @@ namespace Musify.Application.Pictures KeyName = $"{storageConfiguration.Routes.Uploads}/{pictureId}", ContentType = contentType, BucketName = storageConfiguration.BucketName, + EntityType = entityType, + EntityId = EntityId, }; await database.Uploads.AddAsync(upload, cancellationToken); diff --git a/Application/PlayLists/Commands/CreatePlayList/CreatePlayListCommandHandler.cs b/Application/PlayLists/Commands/CreatePlayList/CreatePlayListCommandHandler.cs index 2ac9fe3..76851f7 100644 --- a/Application/PlayLists/Commands/CreatePlayList/CreatePlayListCommandHandler.cs +++ b/Application/PlayLists/Commands/CreatePlayList/CreatePlayListCommandHandler.cs @@ -43,19 +43,24 @@ namespace Musify.Application.PlayLists.Commands.CreatePlayList logger.LogInformation("PlayList with Id={PlayListId} created successfully for UserId={UserId}.", playList.Id, request.UserId); await pictureService.ResizePictureAsync( + EntityType.PlayList, + playList.Id, playList.Id.ToString(), request.PictureContentType, request.PictureStream, [ - new PictureResize(playListConfiguration.SmallPictureWidth, playListConfiguration.SmallPictureHeight), - new PictureResize(playListConfiguration.MediumPictureWidth, playListConfiguration.MediumPictureHeight), - new PictureResize(playListConfiguration.LargePictureWidth, playListConfiguration.LargePictureHeight) + new PictureResize(playListConfiguration.SmallPictureWidth, + playListConfiguration.SmallPictureHeight, playListConfiguration.Routes.SmallPictures), + new PictureResize(playListConfiguration.MediumPictureWidth, + playListConfiguration.MediumPictureHeight, playListConfiguration.Routes.MediumPictures), + new PictureResize(playListConfiguration.LargePictureWidth, + playListConfiguration.LargePictureHeight, playListConfiguration.Routes.LargePictures) ], cancellationToken); logger.LogInformation("Picture for PlayList with Id={PlayListId} ", playList.Id); - return Result.Created(PlayListResponse.Map(playList)); + return Result.Created(PlayListResponse.FromEntity(playList)); } } } \ No newline at end of file diff --git a/Application/PlayLists/Contracts/PlayListResponse.cs b/Application/PlayLists/Contracts/PlayListResponse.cs index ba96c40..8ec1f54 100644 --- a/Application/PlayLists/Contracts/PlayListResponse.cs +++ b/Application/PlayLists/Contracts/PlayListResponse.cs @@ -12,7 +12,7 @@ namespace Musify.Application.PlayLists.Contracts DateTime CreatedAt, DateTime UpdatedAt) { - public static PlayListResponse Map(PlayList playList) + public static PlayListResponse FromEntity(PlayList playList) { return new PlayListResponse( playList.Id, diff --git a/Application/PlayLists/Queries/GetPlayListById/GetPlayListByIdQueryHandler.cs b/Application/PlayLists/Queries/GetPlayListById/GetPlayListByIdQueryHandler.cs index f2bd780..f2313f4 100644 --- a/Application/PlayLists/Queries/GetPlayListById/GetPlayListByIdQueryHandler.cs +++ b/Application/PlayLists/Queries/GetPlayListById/GetPlayListByIdQueryHandler.cs @@ -16,13 +16,7 @@ namespace Musify.Application.PlayLists.Queries.GetPlayListById .SingleOrDefaultAsync(p => p.Id == request.Id, cancellationToken); return playList is not null - ? Result.Success(new PlayListResponse( - playList.Id, - playList.Name, - playList.Description, - playList.ImageName, - playList.CreatedDate, - playList.UpdatedDate)) + ? Result.Success(PlayListResponse.FromEntity(playList)) : Result.NotFound("Playlist not found."); } } diff --git a/Application/PlayLists/Queries/GetPlayLists/GetPlayListsQueryHandler.cs b/Application/PlayLists/Queries/GetPlayLists/GetPlayListsQueryHandler.cs index 78ce41a..ecda141 100644 --- a/Application/PlayLists/Queries/GetPlayLists/GetPlayListsQueryHandler.cs +++ b/Application/PlayLists/Queries/GetPlayLists/GetPlayListsQueryHandler.cs @@ -3,6 +3,7 @@ using DispatchR.Abstractions.Send; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts.Infrastructure; using Musify.Application.PlayLists.Contracts; +using Musify.Domain.Entities; using X.PagedList.EF; namespace Musify.Application.PlayLists.Queries.GetPlayLists @@ -20,13 +21,7 @@ namespace Musify.Application.PlayLists.Queries.GetPlayLists var pagedPlayLists = await database.PlayLists .AsNoTracking() .OrderBy(p => p.Id) - .Select(p => new PlayListResponse( - p.Id, - p.Name, - p.Description, - p.ImageName, - p.CreatedDate, - p.UpdatedDate)) + .Select(p => PlayListResponse.FromEntity(p)) .ToPagedListAsync(pageNumber, pageSize, totalCount, cancellationToken); var response = new PaginatedPlayListResponse( diff --git a/Application/PlayLists/Queries/GetPlayListsByUserId/GetPlayListsByUserIdQueryHandler.cs b/Application/PlayLists/Queries/GetPlayListsByUserId/GetPlayListsByUserIdQueryHandler.cs index 848802b..328895f 100644 --- a/Application/PlayLists/Queries/GetPlayListsByUserId/GetPlayListsByUserIdQueryHandler.cs +++ b/Application/PlayLists/Queries/GetPlayListsByUserId/GetPlayListsByUserIdQueryHandler.cs @@ -3,6 +3,7 @@ using DispatchR.Abstractions.Send; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts.Infrastructure; using Musify.Application.PlayLists.Contracts; +using Musify.Domain.Entities; using X.PagedList.EF; namespace Musify.Application.PlayLists.Queries.GetPlayListsByUserId @@ -27,13 +28,7 @@ namespace Musify.Application.PlayLists.Queries.GetPlayListsByUserId var pagedPlayLists = await playListsQuery .OrderBy(p => p.CreatedDate) - .Select(p => new PlayListResponse( - p.Id, - p.Name, - p.Description, - p.ImageName, - p.CreatedDate, - p.UpdatedDate)) + .Select(p => PlayListResponse.FromEntity(p)) .ToPagedListAsync(pageNumber, pageSize, totalCount, cancellationToken); var response = new PaginatedPlayListResponse( diff --git a/Infrastructure/Messaging/Consumers/ImageResizedConsumer.cs b/Infrastructure/Messaging/Consumers/ImageResizedConsumer.cs index a03800b..88280bb 100644 --- a/Infrastructure/Messaging/Consumers/ImageResizedConsumer.cs +++ b/Infrastructure/Messaging/Consumers/ImageResizedConsumer.cs @@ -1,6 +1,5 @@ using Ardalis.Result; using MassTransit; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Musify.Application.Contracts.Infrastructure; using Musify.Application.Pictures.Events; @@ -15,7 +14,7 @@ namespace Musify.Infrastructure.Messaging.Consumers { try { - var upload = await database.Uploads.SingleOrDefaultAsync(u => u.Id == consumeContext.Message.UploadId); + var upload = await database.Uploads.FindAsync(consumeContext.Message.UploadId); if (upload is null) { @@ -31,53 +30,64 @@ namespace Musify.Infrastructure.Messaging.Consumers await UpdateState(database, upload, UploadState.Processing, consumeContext.CancellationToken); - var file = await storageHandler.GetFileAsync( + var fileResult = await storageHandler.GetFileAsync( upload.BucketName, upload.KeyName, consumeContext.CancellationToken); - if (file.IsNotFound()) + if (fileResult.IsNotFound()) { logger.LogWarning("File not found in storage: BucketName={BucketName}, KeyName={KeyName}", upload.BucketName, upload.KeyName); - await UpdateState(database, upload, UploadState.Failed, consumeContext.CancellationToken); - return; } - using var fileStream = file.Value; + using var fileStream = fileResult.Value; - var pictureResult = await pictureHandler.ResizePictureAsync( - fileStream, - consumeContext.Message.Width, - consumeContext.Message.Height, - consumeContext.CancellationToken); - - if (!pictureResult.IsSuccess) + foreach (var resize in consumeContext.Message.ImageResizes) { - string errors = string.Join("; ", pictureResult.Errors); - logger.LogError("Failed to resize picture: {ErrorMessage}", errors); - - await UpdateState(database, upload, UploadState.Failed, consumeContext.CancellationToken); + var newUpload = new Upload + { + BucketName = upload.BucketName, + KeyName = $"{resize.SaveOnRoute}/{upload.Id}.webp", + ContentType = "image/webp", + State = UploadState.Processing, + EntityId = upload.EntityId, + EntityType = upload.EntityType + }; - return; - } + await database.Uploads.AddAsync(newUpload, consumeContext.CancellationToken); - var saveResult = await storageHandler.UploadFileAsync( - pictureResult.Value, - "image/webp", - upload.BucketName, - $"{consumeContext.Message.SaveRoute}/{upload.Id}.webp", - consumeContext.CancellationToken); + await database.SaveChangesAsync(consumeContext.CancellationToken); - if (!saveResult.IsSuccess) - { - string errors = string.Join("; ", saveResult.Errors); - logger.LogError("Failed to upload resized picture: {ErrorMessage}", errors); + var pictureResult = await pictureHandler.ResizePictureAsync( + fileStream, + resize.Width, + resize.Height, + consumeContext.CancellationToken); - await UpdateState(database, upload, UploadState.Failed, consumeContext.CancellationToken); + if (!pictureResult.IsSuccess) + { + logger.LogError("Failed to resize picture: {ErrorMessage}", string.Join("; ", pictureResult.Errors)); + await UpdateState(database, newUpload, UploadState.Failed, consumeContext.CancellationToken); + continue; + } - return; + var saveResult = await storageHandler.UploadFileAsync( + pictureResult.Value, + "image/webp", + upload.BucketName, + $"{resize.SaveOnRoute}/{upload.Id}.webp", + consumeContext.CancellationToken); + + if (!saveResult.IsSuccess) + { + logger.LogError("Failed to upload resized picture: {ErrorMessage}", string.Join("; ", saveResult.Errors)); + await UpdateState(database, newUpload, UploadState.Failed, consumeContext.CancellationToken); + continue; + } + + await UpdateState(database, newUpload, UploadState.Completed, consumeContext.CancellationToken); } await UpdateState(database, upload, UploadState.Completed, consumeContext.CancellationToken); @@ -88,7 +98,7 @@ namespace Musify.Infrastructure.Messaging.Consumers throw; } } - + async Task UpdateState(IDatabase database, Upload upload, UploadState uploadState, CancellationToken cancellationToken) { upload.State = uploadState; diff --git a/Musify.Backend/Entities/EntityType.cs b/Musify.Backend/Entities/EntityType.cs new file mode 100644 index 0000000..24c2cd9 --- /dev/null +++ b/Musify.Backend/Entities/EntityType.cs @@ -0,0 +1,9 @@ +namespace Musify.Domain.Entities +{ + public enum EntityType + { + User, + Track, + PlayList + } +} \ No newline at end of file diff --git a/Musify.Backend/Entities/Upload.cs b/Musify.Backend/Entities/Upload.cs index 0bb727c..0bb9ca4 100644 --- a/Musify.Backend/Entities/Upload.cs +++ b/Musify.Backend/Entities/Upload.cs @@ -18,6 +18,12 @@ namespace Musify.Domain.Entities [Required] public required string ContentType { get; set; } + [Required] + public required EntityType EntityType { get; set; } + + [Required] + public required Guid EntityId { get; set; } + [Required] public UploadState State { get; set; } = UploadState.Pending;