From 2769c7f38fca04b5702d5e8e9038fcc3a139556d Mon Sep 17 00:00:00 2001 From: XShine555 Date: Thu, 28 May 2026 18:37:54 +0200 Subject: [PATCH] 1 --- .../Events/CreatePlayListResourcesEvent.cs | 12 ++ .../Events/CreateTrackResourcesEvent.cs | 16 +++ .../UpdatePlayListPictureSourceEvent.cs | 12 ++ .../Handlers/CreatePlayListCommandHandler.cs | 70 ++++++------ .../Handlers/UpdatePlayListCommandHandler.cs | 75 +++++++------ .../Handler/CreateTrackCommandHandler.cs | 103 ++++++------------ .../GenerateAudioWorkflowPathsActivity.cs | 1 - .../Files/CopyFileInBucketActivity.cs | 61 +++++++++++ .../Files/RemoveFolderFromBucketActivity.cs | 42 ------- .../GeneratePictureWorkflowPathsActivity.cs | 6 +- ...hPlayListPictureProcessingEventActivity.cs | 34 ++++++ .../PublishTrackProcessingEventsActivity.cs | 43 ++++++++ .../ConsumeUploadIntentsActivity.cs | 62 +++++++++++ .../ConsumeUploadIntentsArguments.cs | 5 + .../Arguments/CopyFileInBucketArguments.cs | 8 ++ ...PlayListPictureProcessingEventArguments.cs | 12 ++ .../PublishTrackProcessingEventsArguments.cs | 14 +++ .../RemoveFolderFromBucketArguments.cs | 6 - .../Consumers/CreatePlayListConsumer.cs | 23 ++++ .../Consumers/CreateTrackConsumer.cs | 23 ++++ .../UpdatePlayListPictureSourceConsumer.cs | 23 ++++ ...TransitDependencyInjection.Registration.cs | 45 ++++++++ .../Logs/GenerateAudioWorkflowPathsLog.cs | 4 - .../MassTransit/RoutingSlip/ActivityNames.cs | 30 ++++- .../Builders/CreateTrackRoutingSlipBuilder.cs | 63 +++++++++++ .../DeletePlayListRoutingSlipBuilder.cs | 8 +- .../Builders/DeleteTrackRoutingSlipBuilder.cs | 14 +-- ...PlayListPictureSourceRoutingSlipBuilder.cs | 84 ++++++++++++++ .../Variables/RoutingSlipVariableNames.cs | 3 - 29 files changed, 683 insertions(+), 219 deletions(-) create mode 100644 Application/Events/CreatePlayListResourcesEvent.cs create mode 100644 Application/Events/CreateTrackResourcesEvent.cs create mode 100644 Application/Events/UpdatePlayListPictureSourceEvent.cs create mode 100644 Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs delete mode 100644 Infrastructure/MassTransit/Activities/Files/RemoveFolderFromBucketActivity.cs create mode 100644 Infrastructure/MassTransit/Activities/PlayLists/PublishPlayListPictureProcessingEventActivity.cs create mode 100644 Infrastructure/MassTransit/Activities/Tracks/PublishTrackProcessingEventsActivity.cs create mode 100644 Infrastructure/MassTransit/Activities/UploadIntents/ConsumeUploadIntentsActivity.cs create mode 100644 Infrastructure/MassTransit/Arguments/ConsumeUploadIntentsArguments.cs create mode 100644 Infrastructure/MassTransit/Arguments/CopyFileInBucketArguments.cs create mode 100644 Infrastructure/MassTransit/Arguments/PublishPlayListPictureProcessingEventArguments.cs create mode 100644 Infrastructure/MassTransit/Arguments/PublishTrackProcessingEventsArguments.cs delete mode 100644 Infrastructure/MassTransit/Arguments/RemoveFolderFromBucketArguments.cs create mode 100644 Infrastructure/MassTransit/Consumers/CreatePlayListConsumer.cs create mode 100644 Infrastructure/MassTransit/Consumers/CreateTrackConsumer.cs create mode 100644 Infrastructure/MassTransit/Consumers/UpdatePlayListPictureSourceConsumer.cs delete mode 100644 Infrastructure/MassTransit/Logs/GenerateAudioWorkflowPathsLog.cs create mode 100644 Infrastructure/MassTransit/RoutingSlip/Builders/CreateTrackRoutingSlipBuilder.cs create mode 100644 Infrastructure/MassTransit/RoutingSlip/Builders/PlayListPictureSourceRoutingSlipBuilder.cs diff --git a/Application/Events/CreatePlayListResourcesEvent.cs b/Application/Events/CreatePlayListResourcesEvent.cs new file mode 100644 index 0000000..89523fb --- /dev/null +++ b/Application/Events/CreatePlayListResourcesEvent.cs @@ -0,0 +1,12 @@ +namespace Musify.Application.Events +{ + public record CreatePlayListResourcesEvent( + Guid PlayListId, + Guid PictureIntentId, + string Bucket, + string PictureSourceKey, + string PictureDestinationKey, + ImageSize Small, + ImageSize Medium, + ImageSize Large); +} diff --git a/Application/Events/CreateTrackResourcesEvent.cs b/Application/Events/CreateTrackResourcesEvent.cs new file mode 100644 index 0000000..987ce4c --- /dev/null +++ b/Application/Events/CreateTrackResourcesEvent.cs @@ -0,0 +1,16 @@ +namespace Musify.Application.Events +{ + public record CreateTrackResourcesEvent( + Guid TrackId, + Guid PictureIntentId, + Guid AudioIntentId, + string Bucket, + string PictureSourceKey, + string PictureDestinationKey, + string AudioSourceKey, + string AudioDestinationKey, + string AudioProcessedFolderKey, + ImageSize Small, + ImageSize Medium, + ImageSize Large); +} diff --git a/Application/Events/UpdatePlayListPictureSourceEvent.cs b/Application/Events/UpdatePlayListPictureSourceEvent.cs new file mode 100644 index 0000000..2638c8d --- /dev/null +++ b/Application/Events/UpdatePlayListPictureSourceEvent.cs @@ -0,0 +1,12 @@ +namespace Musify.Application.Events +{ + public record UpdatePlayListPictureSourceEvent( + Guid PlayListId, + Guid PictureIntentId, + string Bucket, + string PictureSourceKey, + string PictureDestinationKey, + ImageSize Small, + ImageSize Medium, + ImageSize Large); +} diff --git a/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs b/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs index fe9620b..85dd51b 100644 --- a/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs +++ b/Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs @@ -17,7 +17,6 @@ namespace Musify.Application.PlayLists.Handlers IEventBus eventBus, IDatabase database, UploadIntentValidator uploadIntentValidator, - IStorageService storageService, ILogger logger, ApplicationStorageConfiguration storageConfiguration, PlayListConfiguration playListConfiguration, @@ -35,8 +34,8 @@ namespace Musify.Application.PlayLists.Handlers return Result.NotFound($"User {request.UserId} not found"); } - string originalPictureName; UploadIntent? pictureIntent = null; + string originalPictureName; if (request.PictureIntentId.HasValue) { @@ -48,17 +47,6 @@ namespace Musify.Application.PlayLists.Handlers pictureIntent = validation.Value; originalPictureName = pictureIntent.ObjectName; - - var finalKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, originalPictureName); - try - { - await storageService.CopyFileAsync(pictureIntent.Bucket, pictureIntent.Key, pictureIntent.Bucket, finalKey, cancellationToken); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to copy playlist picture from temp {TempKey} to final {FinalKey}", pictureIntent.Key, finalKey); - return Result.Error("Failed to move uploaded file to its final location."); - } } else { @@ -81,9 +69,9 @@ namespace Musify.Application.PlayLists.Handlers if (pictureIntent is not null) { - pictureIntent.Status = UploadIntentStatus.Consumed; - - var publishResult = await PublishPictureUpdateEventAsync(playList, cancellationToken); + var finalPictureKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, originalPictureName); + var publishResult = await PublishCreatePlayListEventAsync( + playList.Id, pictureIntent, finalPictureKey, cancellationToken); if (!publishResult.IsSuccess) return publishResult; } @@ -102,35 +90,41 @@ namespace Musify.Application.PlayLists.Handlers return Result.Created(PlayListApplicationResponse.FromEntity(playList)); } - async Task PublishPictureUpdateEventAsync(PlayList playList, CancellationToken cancellationToken) + async Task> PublishCreatePlayListEventAsync( + Guid playListId, + UploadIntent pictureIntent, + string finalPictureKey, + CancellationToken cancellationToken) { try { - var updateEvent = new UpdatePlayListPictureEvent( - playList.Id, - storageConfiguration.Bucket, - playListConfiguration.Routes.BuildOriginalPicturePath(playList.UserId, playList.OriginalPictureName), - new ImageSize( - playListConfiguration.Routes.SmallPicturesPath, - playListConfiguration.PicturesSizes.SmallPictureWidth, - playListConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - playListConfiguration.Routes.MediumPicturesPath, - playListConfiguration.PicturesSizes.MediumPictureWidth, - playListConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - playListConfiguration.Routes.LargePicturesPath, - playListConfiguration.PicturesSizes.LargePictureWidth, - playListConfiguration.PicturesSizes.LargePictureHeight)); - - await eventBus.PublishAsync(updateEvent, cancellationToken); + await eventBus.PublishAsync( + new CreatePlayListResourcesEvent( + playListId, + pictureIntent.Id, + storageConfiguration.Bucket, + pictureIntent.Key, + finalPictureKey, + new ImageSize( + playListConfiguration.Routes.SmallPicturesPath, + playListConfiguration.PicturesSizes.SmallPictureWidth, + playListConfiguration.PicturesSizes.SmallPictureHeight), + new ImageSize( + playListConfiguration.Routes.MediumPicturesPath, + playListConfiguration.PicturesSizes.MediumPictureWidth, + playListConfiguration.PicturesSizes.MediumPictureHeight), + new ImageSize( + playListConfiguration.Routes.LargePicturesPath, + playListConfiguration.PicturesSizes.LargePictureWidth, + playListConfiguration.PicturesSizes.LargePictureHeight)), + cancellationToken); return Result.Success(); } catch (Exception exception) { - 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}"); + logger.LogError(exception, "Failed to publish create playlist event for playlist {PlayListId}", playListId); + return Result.Error($"Failed to publish create playlist event for playlist {playListId}"); } } } -} \ No newline at end of file +} diff --git a/Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs b/Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs index c1952d8..aeea8f1 100644 --- a/Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs +++ b/Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs @@ -17,7 +17,6 @@ namespace Musify.Application.PlayLists.Handlers IEventBus eventBus, IDatabase database, UploadIntentValidator uploadIntentValidator, - IStorageService storageService, ILogger logger, ApplicationStorageConfiguration storageConfiguration, PlayListConfiguration playListConfiguration, @@ -50,6 +49,9 @@ namespace Musify.Application.PlayLists.Handlers playListEntity.Description = request.NewDescription; } + UploadIntent? pictureIntent = null; + string? finalPictureKey = null; + if (request.NewPictureIntentId.HasValue) { var validation = await uploadIntentValidator.ValidateAndLoadAsync( @@ -58,29 +60,23 @@ namespace Musify.Application.PlayLists.Handlers if (!validation.IsSuccess) return validation.As(); - var intent = validation.Value; - var finalKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, intent.ObjectName); - try - { - await storageService.CopyFileAsync(intent.Bucket, intent.Key, intent.Bucket, finalKey, cancellationToken); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to copy playlist picture from temp {TempKey} to final {FinalKey}", intent.Key, finalKey); - return Result.Error("Failed to move uploaded file to its final location."); - } + pictureIntent = validation.Value; + playListEntity.OriginalPictureName = pictureIntent.ObjectName; + finalPictureKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, pictureIntent.ObjectName); + } - playListEntity.OriginalPictureName = intent.ObjectName; - intent.Status = UploadIntentStatus.Consumed; + database.PlayLists.Update(playListEntity); - var publishResult = await PublishPlayListPictureEvent(playListEntity.UserId, playListEntity.Id, playListEntity.OriginalPictureName, cancellationToken); + if (pictureIntent is not null && finalPictureKey is not null) + { + var publishResult = await PublishUpdatePlayListPictureSourceEventAsync( + playListEntity.Id, pictureIntent, finalPictureKey, cancellationToken); if (!publishResult.IsSuccess) return publishResult; } try { - database.PlayLists.Update(playListEntity); await database.SaveChangesAsync(cancellationToken); } catch (Exception exception) @@ -93,34 +89,41 @@ namespace Musify.Application.PlayLists.Handlers return Result.Success(PlayListApplicationResponse.FromEntity(playListEntity)); } - async Task PublishPlayListPictureEvent(Guid userId, Guid playListId, string originalPictureName, CancellationToken cancellationToken) + async Task> PublishUpdatePlayListPictureSourceEventAsync( + Guid playListId, + UploadIntent pictureIntent, + string finalPictureKey, + CancellationToken cancellationToken) { try { - await eventBus.PublishAsync(new UpdatePlayListPictureEvent( - playListId, - storageConfiguration.Bucket, - playListConfiguration.Routes.BuildOriginalPicturePath(userId, originalPictureName), - new ImageSize( - playListConfiguration.Routes.SmallPicturesPath, - playListConfiguration.PicturesSizes.SmallPictureWidth, - playListConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - playListConfiguration.Routes.MediumPicturesPath, - playListConfiguration.PicturesSizes.MediumPictureWidth, - playListConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - playListConfiguration.Routes.LargePicturesPath, - playListConfiguration.PicturesSizes.LargePictureWidth, - playListConfiguration.PicturesSizes.LargePictureHeight)), + await eventBus.PublishAsync( + new UpdatePlayListPictureSourceEvent( + playListId, + pictureIntent.Id, + storageConfiguration.Bucket, + pictureIntent.Key, + finalPictureKey, + new ImageSize( + playListConfiguration.Routes.SmallPicturesPath, + playListConfiguration.PicturesSizes.SmallPictureWidth, + playListConfiguration.PicturesSizes.SmallPictureHeight), + new ImageSize( + playListConfiguration.Routes.MediumPicturesPath, + playListConfiguration.PicturesSizes.MediumPictureWidth, + playListConfiguration.PicturesSizes.MediumPictureHeight), + new ImageSize( + playListConfiguration.Routes.LargePicturesPath, + playListConfiguration.PicturesSizes.LargePictureWidth, + playListConfiguration.PicturesSizes.LargePictureHeight)), cancellationToken); return Result.Success(); } catch (Exception exception) { - logger.LogError(exception, "Failed to publish playlist picture update event for playlist {PlayListId}", playListId); - return Result.Error($"Failed to publish playlist {playListId} picture update event"); + logger.LogError(exception, "Failed to publish update playlist picture source event for playlist {PlayListId}", playListId); + return Result.Error($"Failed to publish update playlist picture source event for playlist {playListId}"); } } } -} \ No newline at end of file +} diff --git a/Application/Tracks/Handler/CreateTrackCommandHandler.cs b/Application/Tracks/Handler/CreateTrackCommandHandler.cs index 9670714..7f4fbe9 100644 --- a/Application/Tracks/Handler/CreateTrackCommandHandler.cs +++ b/Application/Tracks/Handler/CreateTrackCommandHandler.cs @@ -17,7 +17,6 @@ namespace Musify.Application.Tracks.Handler IDatabase database, IEventBus eventBus, UploadIntentValidator uploadIntentValidator, - IStorageService storageService, ILogger logger, ApplicationStorageConfiguration storageConfiguration, TrackConfiguration trackConfiguration, @@ -51,17 +50,7 @@ namespace Musify.Application.Tracks.Handler var finalPictureKey = trackConfiguration.Routes.BuildOriginalPicturePath(request.UserId, pictureIntent.ObjectName); var finalAudioKey = trackConfiguration.Routes.BuildOriginalAudioPath(request.UserId, audioIntent.ObjectName); - - try - { - await storageService.CopyFileAsync(pictureIntent.Bucket, pictureIntent.Key, pictureIntent.Bucket, finalPictureKey, cancellationToken); - await storageService.CopyFileAsync(audioIntent.Bucket, audioIntent.Key, audioIntent.Bucket, finalAudioKey, cancellationToken); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to copy track files from temp to final location for user {UserId}", request.UserId); - return Result.Error("Failed to move uploaded files to their final locations."); - } + var audioProcessedFolderKey = trackConfiguration.Routes.BuildProcessedAudioPath(Guid.NewGuid().ToString()); var trackEntity = new Track { @@ -78,16 +67,38 @@ namespace Musify.Application.Tracks.Handler await database.Tracks.AddAsync(trackEntity, cancellationToken); - pictureIntent.Status = UploadIntentStatus.Consumed; - audioIntent.Status = UploadIntentStatus.Consumed; - - var publishPictureResult = await PublishUpdateEvent(request.UserId, trackEntity, cancellationToken); - if (!publishPictureResult.IsSuccess) - return Result.Error($"Failed to create track for {request.Title}"); - - var publishTranscodeResult = await PublishTranscodeEvent(request.UserId, trackEntity, cancellationToken); - if (!publishTranscodeResult.IsSuccess) + try + { + await eventBus.PublishAsync( + new CreateTrackResourcesEvent( + trackEntity.Id, + pictureIntent.Id, + audioIntent.Id, + storageConfiguration.Bucket, + pictureIntent.Key, + finalPictureKey, + audioIntent.Key, + finalAudioKey, + audioProcessedFolderKey, + new ImageSize( + trackConfiguration.Routes.SmallPicturesPath, + trackConfiguration.PicturesSizes.SmallPictureWidth, + trackConfiguration.PicturesSizes.SmallPictureHeight), + new ImageSize( + trackConfiguration.Routes.MediumPicturesPath, + trackConfiguration.PicturesSizes.MediumPictureWidth, + trackConfiguration.PicturesSizes.MediumPictureHeight), + new ImageSize( + trackConfiguration.Routes.LargePicturesPath, + trackConfiguration.PicturesSizes.LargePictureWidth, + trackConfiguration.PicturesSizes.LargePictureHeight)), + cancellationToken); + } + catch (Exception exception) + { + logger.LogError(exception, "Failed to publish create track event for track {TrackId}", trackEntity.Id); return Result.Error($"Failed to create track for {request.Title}"); + } try { @@ -101,55 +112,5 @@ namespace Musify.Application.Tracks.Handler return Result.Created(TrackApplicationResponse.FromEntity(trackEntity)); } - - async Task PublishUpdateEvent(Guid userId, Track track, CancellationToken cancellationToken) - { - try - { - await eventBus.PublishAsync(new UpdateTrackPictureEvent( - track.Id, - storageConfiguration.Bucket, - trackConfiguration.Routes.BuildOriginalPicturePath(userId, track.OriginalPictureName), - new ImageSize( - trackConfiguration.Routes.SmallPicturesPath, - trackConfiguration.PicturesSizes.SmallPictureWidth, - trackConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - trackConfiguration.Routes.MediumPicturesPath, - trackConfiguration.PicturesSizes.MediumPictureWidth, - trackConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - trackConfiguration.Routes.LargePicturesPath, - trackConfiguration.PicturesSizes.LargePictureWidth, - trackConfiguration.PicturesSizes.LargePictureHeight)), cancellationToken); - return Result.Success(); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to publish track picture update event for track {TrackId}", track.Id); - return Result.Error($"Failed to publish track picture update event for track {track.Id}"); - } - } - - async Task PublishTranscodeEvent(Guid userId, Track track, CancellationToken cancellationToken) - { - var destinationFolderAudio = trackConfiguration.Routes.BuildProcessedAudioPath(Guid.NewGuid().ToString()); - - try - { - await eventBus.PublishAsync(new UpdateTrackAudioEvent( - track.Id, - storageConfiguration.Bucket, - trackConfiguration.Routes.BuildOriginalAudioPath(userId, track.OriginalAudioName), - storageConfiguration.Bucket, - destinationFolderAudio), cancellationToken); - return Result.Success(); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to publish track audio update event for track {TrackId}", track.Id); - return Result.Error($"Failed to publish track audio update event for track {track.Id}"); - } - } } } diff --git a/Infrastructure/MassTransit/Activities/Audio/GenerateAudioWorkflowPathsActivity.cs b/Infrastructure/MassTransit/Activities/Audio/GenerateAudioWorkflowPathsActivity.cs index 73f4dcc..b53337f 100644 --- a/Infrastructure/MassTransit/Activities/Audio/GenerateAudioWorkflowPathsActivity.cs +++ b/Infrastructure/MassTransit/Activities/Audio/GenerateAudioWorkflowPathsActivity.cs @@ -45,7 +45,6 @@ namespace Musify.Infrastructure.MassTransit.Activities return executeContext.CompletedWithVariables(new Dictionary { [RoutingSlipVariableNames.Workflow.TemporalDirectory] = workingDirectory, - [RoutingSlipVariableNames.Audio.WorkingDirectory] = workingDirectory, [RoutingSlipVariableNames.Audio.SourceFilePath] = sourceFilePath, [RoutingSlipVariableNames.Audio.TranscodedDirectory] = workingDirectory } ); diff --git a/Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs b/Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs new file mode 100644 index 0000000..52ce5a7 --- /dev/null +++ b/Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs @@ -0,0 +1,61 @@ +using MassTransit; +using Microsoft.Extensions.Logging; +using Musify.Application.Contracts.Infrastructure; +using Musify.Infrastructure.MassTransit.Arguments; +using Musify.Infrastructure.MassTransit.Logs; + +namespace Musify.Infrastructure.MassTransit.Activities.Files +{ + internal class CopyFileInBucketActivity( + IStorageService storageHandler, + ILogger logger) + : IActivity + { + public const string ExecuteEndpointName = "copy-file-in-bucket"; + + public async Task Execute(ExecuteContext executeContext) + { + try + { + await storageHandler.CopyFileAsync( + executeContext.Arguments.SourceBucket, + executeContext.Arguments.SourceKey, + executeContext.Arguments.DestinationBucket, + executeContext.Arguments.DestinationKey, + executeContext.CancellationToken); + + return executeContext.Completed(new CopyFileInBucketLog( + executeContext.Arguments.DestinationBucket, + executeContext.Arguments.DestinationKey)); + } + catch (Exception exception) + { + logger.LogError(exception, "Failed to copy {SourceBucket}/{SourceKey} to {DestinationBucket}/{DestinationKey}", + executeContext.Arguments.SourceBucket, + executeContext.Arguments.SourceKey, + executeContext.Arguments.DestinationBucket, + executeContext.Arguments.DestinationKey); + throw; + } + } + + public async Task Compensate(CompensateContext compensateContext) + { + try + { + await storageHandler.RemoveFileAsync( + compensateContext.Log.DestinationBucket, + compensateContext.Log.DestinationKey, + compensateContext.CancellationToken); + return compensateContext.Compensated(); + } + catch (Exception exception) + { + logger.LogError(exception, "Failed to compensate copied file {Bucket}/{Key}", + compensateContext.Log.DestinationBucket, + compensateContext.Log.DestinationKey); + return compensateContext.Failed(exception); + } + } + } +} diff --git a/Infrastructure/MassTransit/Activities/Files/RemoveFolderFromBucketActivity.cs b/Infrastructure/MassTransit/Activities/Files/RemoveFolderFromBucketActivity.cs deleted file mode 100644 index 91addc2..0000000 --- a/Infrastructure/MassTransit/Activities/Files/RemoveFolderFromBucketActivity.cs +++ /dev/null @@ -1,42 +0,0 @@ -using MassTransit; -using Microsoft.Extensions.Logging; -using Musify.Application.Contracts.Infrastructure; -using Musify.Infrastructure.MassTransit.Arguments; - -namespace Musify.Infrastructure.MassTransit.Activities.Files -{ - internal class RemoveFolderFromBucketActivity( - IStorageService storageHandler, - ILogger logger) - : IExecuteActivity - { - public const string ExecuteEndpointName = "remove-folder-from-bucket"; - - public async Task Execute(ExecuteContext executeContext) - { - var folderKey = executeContext.GetVariable(executeContext.Arguments.FolderKeyVariable); - ArgumentException.ThrowIfNullOrEmpty(folderKey, nameof(folderKey)); - - try - { - await storageHandler.RemoveFolderAsync( - executeContext.Arguments.Bucket, - folderKey, - executeContext.CancellationToken); - - logger.LogInformation("Removed folder {FolderKey} from bucket {Bucket}", - folderKey, - executeContext.Arguments.Bucket); - - return executeContext.Completed(); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to remove folder {FolderKey} from bucket {Bucket}", - folderKey, - executeContext.Arguments.Bucket); - throw; - } - } - } -} \ No newline at end of file diff --git a/Infrastructure/MassTransit/Activities/Pictures/GeneratePictureWorkflowPathsActivity.cs b/Infrastructure/MassTransit/Activities/Pictures/GeneratePictureWorkflowPathsActivity.cs index 5d2570a..be2f675 100644 --- a/Infrastructure/MassTransit/Activities/Pictures/GeneratePictureWorkflowPathsActivity.cs +++ b/Infrastructure/MassTransit/Activities/Pictures/GeneratePictureWorkflowPathsActivity.cs @@ -16,8 +16,7 @@ namespace Musify.Infrastructure.MassTransit.Activities { try { - var destinationFolderName = Guid.NewGuid().ToString(); - var workingDirectory = Path.Combine(executeContext.Arguments.TemporaryRootDirectory, destinationFolderName); + var workingDirectory = Path.Combine(executeContext.Arguments.TemporaryRootDirectory, Guid.NewGuid().ToString()); var sourceFilePath = Path.Combine( workingDirectory, Guid.NewGuid().ToString() + Path.GetExtension(executeContext.Arguments.SourceKey)); @@ -38,8 +37,7 @@ namespace Musify.Infrastructure.MassTransit.Activities [RoutingSlipVariableNames.Picture.OriginalFilePath] = sourceFilePath, [RoutingSlipVariableNames.Picture.SmallResizedFilePath] = smallPictureFilePath, [RoutingSlipVariableNames.Picture.MediumResizedFilePath] = mediumPictureFilePath, - [RoutingSlipVariableNames.Picture.LargeResizedFilePath] = largePictureFilePath, - [RoutingSlipVariableNames.Picture.DestinationFolderName] = destinationFolderName + [RoutingSlipVariableNames.Picture.LargeResizedFilePath] = largePictureFilePath } ); } catch (Exception exception) diff --git a/Infrastructure/MassTransit/Activities/PlayLists/PublishPlayListPictureProcessingEventActivity.cs b/Infrastructure/MassTransit/Activities/PlayLists/PublishPlayListPictureProcessingEventActivity.cs new file mode 100644 index 0000000..7754510 --- /dev/null +++ b/Infrastructure/MassTransit/Activities/PlayLists/PublishPlayListPictureProcessingEventActivity.cs @@ -0,0 +1,34 @@ +using MassTransit; +using Microsoft.Extensions.Logging; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.Arguments; + +namespace Musify.Infrastructure.MassTransit.Activities.PlayLists +{ + internal class PublishPlayListPictureProcessingEventActivity( + IPublishEndpoint publishEndpoint, + ILogger logger) + : IExecuteActivity + { + public const string ExecuteEndpointName = "publish-playList-picture-processing-event"; + + public async Task Execute(ExecuteContext executeContext) + { + var arguments = executeContext.Arguments; + + await publishEndpoint.Publish( + new UpdatePlayListPictureEvent( + arguments.PlayListId, + arguments.Bucket, + arguments.FinalPictureKey, + arguments.Small, + arguments.Medium, + arguments.Large), + executeContext.CancellationToken); + + logger.LogInformation("Published picture processing event for playlist {PlayListId}", arguments.PlayListId); + + return executeContext.Completed(); + } + } +} diff --git a/Infrastructure/MassTransit/Activities/Tracks/PublishTrackProcessingEventsActivity.cs b/Infrastructure/MassTransit/Activities/Tracks/PublishTrackProcessingEventsActivity.cs new file mode 100644 index 0000000..a82865c --- /dev/null +++ b/Infrastructure/MassTransit/Activities/Tracks/PublishTrackProcessingEventsActivity.cs @@ -0,0 +1,43 @@ +using MassTransit; +using Microsoft.Extensions.Logging; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.Arguments; + +namespace Musify.Infrastructure.MassTransit.Activities.Tracks +{ + internal class PublishTrackProcessingEventsActivity( + IPublishEndpoint publishEndpoint, + ILogger logger) + : IExecuteActivity + { + public const string ExecuteEndpointName = "publish-track-processing-events"; + + public async Task Execute(ExecuteContext executeContext) + { + var arguments = executeContext.Arguments; + + await publishEndpoint.Publish( + new UpdateTrackPictureEvent( + arguments.TrackId, + arguments.Bucket, + arguments.FinalPictureKey, + arguments.Small, + arguments.Medium, + arguments.Large), + executeContext.CancellationToken); + + await publishEndpoint.Publish( + new UpdateTrackAudioEvent( + arguments.TrackId, + arguments.Bucket, + arguments.FinalAudioKey, + arguments.Bucket, + arguments.AudioDestinationFolderKey), + executeContext.CancellationToken); + + logger.LogInformation("Published processing events for track {TrackId}", arguments.TrackId); + + return executeContext.Completed(); + } + } +} diff --git a/Infrastructure/MassTransit/Activities/UploadIntents/ConsumeUploadIntentsActivity.cs b/Infrastructure/MassTransit/Activities/UploadIntents/ConsumeUploadIntentsActivity.cs new file mode 100644 index 0000000..15cb3ef --- /dev/null +++ b/Infrastructure/MassTransit/Activities/UploadIntents/ConsumeUploadIntentsActivity.cs @@ -0,0 +1,62 @@ +using MassTransit; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Musify.Application.Contracts.Infrastructure; +using Musify.Domain.Entities; +using Musify.Infrastructure.MassTransit.Arguments; +using Musify.Infrastructure.MassTransit.Logs; + +namespace Musify.Infrastructure.MassTransit.Activities.UploadIntents +{ + internal class ConsumeUploadIntentsActivity( + IDatabase database, + ILogger logger) + : IActivity + { + public const string ExecuteEndpointName = "consume-upload-intents"; + + public async Task Execute(ExecuteContext executeContext) + { + var intentIds = executeContext.Arguments.IntentIds; + + var intents = await database.UploadIntents + .Where(i => intentIds.Contains(i.Id)) + .ToListAsync(executeContext.CancellationToken); + + foreach (var intent in intents) + intent.Status = UploadIntentStatus.Consumed; + + await database.SaveChangesAsync(executeContext.CancellationToken); + + logger.LogInformation("Marked {Count} upload intent(s) as consumed", intents.Count); + + return executeContext.Completed(new ConsumeUploadIntentsLog(intentIds)); + } + + public async Task Compensate(CompensateContext compensateContext) + { + try + { + var intentIds = compensateContext.Log.IntentIds; + + var intents = await database.UploadIntents + .Where(i => intentIds.Contains(i.Id)) + .ToListAsync(compensateContext.CancellationToken); + + foreach (var intent in intents) + intent.Status = UploadIntentStatus.Issued; + + await database.SaveChangesAsync(compensateContext.CancellationToken); + + logger.LogInformation("Reverted {Count} upload intent(s) back to Issued", intents.Count); + + return compensateContext.Compensated(); + } + catch (Exception exception) + { + logger.LogError(exception, "Failed to compensate upload intent consumption"); + return compensateContext.Failed(exception); + } + } + } +} diff --git a/Infrastructure/MassTransit/Arguments/ConsumeUploadIntentsArguments.cs b/Infrastructure/MassTransit/Arguments/ConsumeUploadIntentsArguments.cs new file mode 100644 index 0000000..70cd9c2 --- /dev/null +++ b/Infrastructure/MassTransit/Arguments/ConsumeUploadIntentsArguments.cs @@ -0,0 +1,5 @@ +namespace Musify.Infrastructure.MassTransit.Arguments +{ + public record ConsumeUploadIntentsArguments( + Guid[] IntentIds); +} diff --git a/Infrastructure/MassTransit/Arguments/CopyFileInBucketArguments.cs b/Infrastructure/MassTransit/Arguments/CopyFileInBucketArguments.cs new file mode 100644 index 0000000..ade186a --- /dev/null +++ b/Infrastructure/MassTransit/Arguments/CopyFileInBucketArguments.cs @@ -0,0 +1,8 @@ +namespace Musify.Infrastructure.MassTransit.Arguments +{ + public record CopyFileInBucketArguments( + string SourceBucket, + string SourceKey, + string DestinationBucket, + string DestinationKey); +} diff --git a/Infrastructure/MassTransit/Arguments/PublishPlayListPictureProcessingEventArguments.cs b/Infrastructure/MassTransit/Arguments/PublishPlayListPictureProcessingEventArguments.cs new file mode 100644 index 0000000..2b402ca --- /dev/null +++ b/Infrastructure/MassTransit/Arguments/PublishPlayListPictureProcessingEventArguments.cs @@ -0,0 +1,12 @@ +using Musify.Application.Events; + +namespace Musify.Infrastructure.MassTransit.Arguments +{ + public record PublishPlayListPictureProcessingEventArguments( + Guid PlayListId, + string Bucket, + string FinalPictureKey, + ImageSize Small, + ImageSize Medium, + ImageSize Large); +} diff --git a/Infrastructure/MassTransit/Arguments/PublishTrackProcessingEventsArguments.cs b/Infrastructure/MassTransit/Arguments/PublishTrackProcessingEventsArguments.cs new file mode 100644 index 0000000..aebba17 --- /dev/null +++ b/Infrastructure/MassTransit/Arguments/PublishTrackProcessingEventsArguments.cs @@ -0,0 +1,14 @@ +using Musify.Application.Events; + +namespace Musify.Infrastructure.MassTransit.Arguments +{ + public record PublishTrackProcessingEventsArguments( + Guid TrackId, + string Bucket, + string FinalPictureKey, + string FinalAudioKey, + string AudioDestinationFolderKey, + ImageSize Small, + ImageSize Medium, + ImageSize Large); +} diff --git a/Infrastructure/MassTransit/Arguments/RemoveFolderFromBucketArguments.cs b/Infrastructure/MassTransit/Arguments/RemoveFolderFromBucketArguments.cs deleted file mode 100644 index 5628a4f..0000000 --- a/Infrastructure/MassTransit/Arguments/RemoveFolderFromBucketArguments.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Musify.Infrastructure.MassTransit.Arguments -{ - public record RemoveFolderFromBucketArguments( - string Bucket, - string FolderKeyVariable); -} diff --git a/Infrastructure/MassTransit/Consumers/CreatePlayListConsumer.cs b/Infrastructure/MassTransit/Consumers/CreatePlayListConsumer.cs new file mode 100644 index 0000000..218e9bf --- /dev/null +++ b/Infrastructure/MassTransit/Consumers/CreatePlayListConsumer.cs @@ -0,0 +1,23 @@ +using MassTransit; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.RoutingSlip.Builders; + +namespace Musify.Infrastructure.MassTransit.Consumers +{ + public class CreatePlayListConsumer( + IBus bus, + PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder) + : IConsumer + { + public const string QueueName = "create-playList"; + + public async Task Consume(ConsumeContext consumeContext) + { + var routingSlip = routingSlipBuilder + .Build(consumeContext.Message, consumeContext.CorrelationId) + .Build(); + + await bus.Execute(routingSlip); + } + } +} diff --git a/Infrastructure/MassTransit/Consumers/CreateTrackConsumer.cs b/Infrastructure/MassTransit/Consumers/CreateTrackConsumer.cs new file mode 100644 index 0000000..06d4441 --- /dev/null +++ b/Infrastructure/MassTransit/Consumers/CreateTrackConsumer.cs @@ -0,0 +1,23 @@ +using MassTransit; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.RoutingSlip.Builders; + +namespace Musify.Infrastructure.MassTransit.Consumers +{ + public class CreateTrackConsumer( + IBus bus, + CreateTrackRoutingSlipBuilder routingSlipBuilder) + : IConsumer + { + public const string QueueName = "create-track"; + + public async Task Consume(ConsumeContext consumeContext) + { + var routingSlip = routingSlipBuilder + .Build(consumeContext.Message, consumeContext.CorrelationId) + .Build(); + + await bus.Execute(routingSlip); + } + } +} diff --git a/Infrastructure/MassTransit/Consumers/UpdatePlayListPictureSourceConsumer.cs b/Infrastructure/MassTransit/Consumers/UpdatePlayListPictureSourceConsumer.cs new file mode 100644 index 0000000..f24e9dd --- /dev/null +++ b/Infrastructure/MassTransit/Consumers/UpdatePlayListPictureSourceConsumer.cs @@ -0,0 +1,23 @@ +using MassTransit; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.RoutingSlip.Builders; + +namespace Musify.Infrastructure.MassTransit.Consumers +{ + public class UpdatePlayListPictureSourceConsumer( + IBus bus, + PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder) + : IConsumer + { + public const string QueueName = "update-playList-picture-source"; + + public async Task Consume(ConsumeContext consumeContext) + { + var routingSlip = routingSlipBuilder + .Build(consumeContext.Message, consumeContext.CorrelationId) + .Build(); + + await bus.Execute(routingSlip); + } + } +} diff --git a/Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs b/Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs index 860efac..438b5e6 100644 --- a/Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs +++ b/Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs @@ -8,6 +8,7 @@ using Musify.Infrastructure.MassTransit.Activities.Files; using Musify.Infrastructure.MassTransit.Activities.Logs; using Musify.Infrastructure.MassTransit.Activities.PlayLists; using Musify.Infrastructure.MassTransit.Activities.Tracks; +using Musify.Infrastructure.MassTransit.Activities.UploadIntents; using Musify.Infrastructure.MassTransit.Arguments; using Musify.Infrastructure.MassTransit.Consumers; using Musify.Infrastructure.MassTransit.Logs; @@ -23,6 +24,8 @@ namespace Musify.Infrastructure.MassTransit services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); } static void RegisterConsumersAndActivities(IBusRegistrationConfigurator options) @@ -33,6 +36,9 @@ namespace Musify.Infrastructure.MassTransit options.AddConsumer(); options.AddConsumer(); options.AddConsumer(); + options.AddConsumer(); + options.AddConsumer(); + options.AddConsumer(); options.AddExecuteActivity(); options.AddExecuteActivity(); @@ -41,6 +47,8 @@ namespace Musify.Infrastructure.MassTransit options.AddExecuteActivity(); options.AddExecuteActivity(); options.AddExecuteActivity(); + options.AddExecuteActivity(); + options.AddExecuteActivity(); options.AddActivity(); options.AddActivity(); @@ -50,6 +58,8 @@ namespace Musify.Infrastructure.MassTransit options.AddActivity(); options.AddActivity(); options.AddActivity(); + options.AddActivity(); + options.AddActivity(); } static void ConfigureRabbitMqWorkerEndpoints( @@ -85,6 +95,21 @@ namespace Musify.Infrastructure.MassTransit busRegistrationContext, DeletePlayListConsumer.QueueName); + ConfigureConsumerEndpoint( + busFactoryConfigurator, + busRegistrationContext, + CreateTrackConsumer.QueueName); + + ConfigureConsumerEndpoint( + busFactoryConfigurator, + busRegistrationContext, + CreatePlayListConsumer.QueueName); + + ConfigureConsumerEndpoint( + busFactoryConfigurator, + busRegistrationContext, + UpdatePlayListPictureSourceConsumer.QueueName); + ConfigureConsumerEndpoint( busFactoryConfigurator, busRegistrationContext, @@ -125,6 +150,16 @@ namespace Musify.Infrastructure.MassTransit busRegistrationContext, DeletePlayListFromDbActivity.ExecuteEndpointName); + ConfigureExecuteActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + PublishTrackProcessingEventsActivity.ExecuteEndpointName); + + ConfigureExecuteActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName); + ConfigureActivityEndpoint( busFactoryConfigurator, busRegistrationContext, @@ -164,6 +199,16 @@ namespace Musify.Infrastructure.MassTransit busFactoryConfigurator, busRegistrationContext, UploadFileToBucketActivity.ExecuteEndpointName); + + ConfigureActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + CopyFileInBucketActivity.ExecuteEndpointName); + + ConfigureActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + ConsumeUploadIntentsActivity.ExecuteEndpointName); } } } diff --git a/Infrastructure/MassTransit/Logs/GenerateAudioWorkflowPathsLog.cs b/Infrastructure/MassTransit/Logs/GenerateAudioWorkflowPathsLog.cs deleted file mode 100644 index fc2d8ac..0000000 --- a/Infrastructure/MassTransit/Logs/GenerateAudioWorkflowPathsLog.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Musify.Infrastructure.MassTransit.Activities.Logs -{ - public record GenerateAudioWorkflowPathsLog(string WorkingDirectory); -} diff --git a/Infrastructure/MassTransit/RoutingSlip/ActivityNames.cs b/Infrastructure/MassTransit/RoutingSlip/ActivityNames.cs index 71d037d..3767c6c 100644 --- a/Infrastructure/MassTransit/RoutingSlip/ActivityNames.cs +++ b/Infrastructure/MassTransit/RoutingSlip/ActivityNames.cs @@ -2,26 +2,50 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip { internal static class ActivityNames { - internal const string DeleteTrack = "DeleteTrack"; internal const string MarkTrackAsRemoving = "MarkTrackAsRemoving"; internal const string DeleteTrackFromDb = "DeleteTrackFromDb"; internal const string MarkPlayListAsRemoving = "MarkPlayListAsRemoving"; internal const string DeletePlayListFromDb = "DeletePlayListFromDb"; + internal const string GenerateAudioWorkflowPaths = "GenerateAudioWorkflowPaths"; internal const string GeneratePictureWorkflowPaths = "GeneratePictureWorkflowPaths"; + internal const string DownloadFile = "DownloadFile"; + internal const string TranscodeAudio = "TranscodeAudio"; + internal const string ResizeSmall = "ResizeSmall"; internal const string ResizeMedium = "ResizeMedium"; internal const string ResizeLarge = "ResizeLarge"; + internal const string UploadSmall = "UploadSmall"; internal const string UploadMedium = "UploadMedium"; internal const string UploadLarge = "UploadLarge"; + internal const string TransferFiles = "TransferFiles"; - internal const string RemoveFile = "RemoveFile"; - internal const string DeleteOriginal = "DeleteOriginal"; + internal const string UpdateTrackPicture = "UpdateTrackPicture"; internal const string UpdatePlayListPicture = "UpdatePlayListPicture"; internal const string UpdateTrackAudio = "UpdateTrackAudio"; + + internal const string CopyPictureToFinal = "CopyPictureToFinal"; + internal const string CopyAudioToFinal = "CopyAudioToFinal"; + + internal const string ConsumeUploadIntents = "ConsumeUploadIntents"; + + internal const string PublishTrackProcessingEvents = "PublishTrackProcessingEvents"; + internal const string PublishPlayListPictureProcessingEvent = "PublishPlayListPictureProcessingEvent"; + + internal const string RemoveTrackOriginalPicture = "RemoveTrackOriginalPicture"; + internal const string RemoveTrackSmallPicture = "RemoveTrackSmallPicture"; + internal const string RemoveTrackMediumPicture = "RemoveTrackMediumPicture"; + internal const string RemoveTrackLargePicture = "RemoveTrackLargePicture"; + internal const string RemoveTrackOriginalAudio = "RemoveTrackOriginalAudio"; + internal const string RemoveTrackProcessedAudio = "RemoveTrackProcessedAudio"; + + internal const string RemovePlayListOriginalPicture = "RemovePlayListOriginalPicture"; + internal const string RemovePlayListSmallPicture = "RemovePlayListSmallPicture"; + internal const string RemovePlayListMediumPicture = "RemovePlayListMediumPicture"; + internal const string RemovePlayListLargePicture = "RemovePlayListLargePicture"; } } diff --git a/Infrastructure/MassTransit/RoutingSlip/Builders/CreateTrackRoutingSlipBuilder.cs b/Infrastructure/MassTransit/RoutingSlip/Builders/CreateTrackRoutingSlipBuilder.cs new file mode 100644 index 0000000..fd9612f --- /dev/null +++ b/Infrastructure/MassTransit/RoutingSlip/Builders/CreateTrackRoutingSlipBuilder.cs @@ -0,0 +1,63 @@ +using MassTransit; +using MassTransit.Courier.Contracts; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.Activities.Files; +using Musify.Infrastructure.MassTransit.Activities.Tracks; +using Musify.Infrastructure.MassTransit.Activities.UploadIntents; +using Musify.Infrastructure.MassTransit.Arguments; +using Musify.Infrastructure.MassTransit.Consumers; + +namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders +{ + public class CreateTrackRoutingSlipBuilder + { + public RoutingSlipBuilder Build(CreateTrackResourcesEvent message, Guid? correlationId) + { + var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid()); + routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty); + + routingSlipBuilder.AddSubscription( + EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName), + RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted); + + routingSlipBuilder.AddActivity( + ActivityNames.CopyPictureToFinal, + EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName), + new CopyFileInBucketArguments( + message.Bucket, + message.PictureSourceKey, + message.Bucket, + message.PictureDestinationKey)); + + routingSlipBuilder.AddActivity( + ActivityNames.CopyAudioToFinal, + EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName), + new CopyFileInBucketArguments( + message.Bucket, + message.AudioSourceKey, + message.Bucket, + message.AudioDestinationKey)); + + routingSlipBuilder.AddActivity( + ActivityNames.ConsumeUploadIntents, + EndpointHelper.BuildExecuteActivityUri(ConsumeUploadIntentsActivity.ExecuteEndpointName), + new ConsumeUploadIntentsArguments( + [message.PictureIntentId, message.AudioIntentId])); + + routingSlipBuilder.AddActivity( + ActivityNames.PublishTrackProcessingEvents, + EndpointHelper.BuildExecuteActivityUri(PublishTrackProcessingEventsActivity.ExecuteEndpointName), + new PublishTrackProcessingEventsArguments( + message.TrackId, + message.Bucket, + message.PictureDestinationKey, + message.AudioDestinationKey, + message.AudioProcessedFolderKey, + message.Small, + message.Medium, + message.Large)); + + return routingSlipBuilder; + } + } +} diff --git a/Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs b/Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs index f12750d..1d6efa8 100644 --- a/Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs +++ b/Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs @@ -45,7 +45,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders if (playList.OriginalPictureName != routes.PresetOriginalPicture) { routingSlipBuilder.AddActivity( - "RemovePlayListOriginalPicture", + ActivityNames.RemovePlayListOriginalPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, @@ -55,7 +55,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders if (playList.SmallPictureName != routes.PresetSmallPicture) { routingSlipBuilder.AddActivity( - "RemovePlayListSmallPicture", + ActivityNames.RemovePlayListSmallPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, @@ -65,7 +65,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders if (playList.MediumPictureName != routes.PresetMediumPicture) { routingSlipBuilder.AddActivity( - "RemovePlayListMediumPicture", + ActivityNames.RemovePlayListMediumPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, @@ -75,7 +75,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders if (playList.LargePictureName != routes.PresetLargePicture) { routingSlipBuilder.AddActivity( - "RemovePlayListLargePicture", + ActivityNames.RemovePlayListLargePicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, diff --git a/Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs b/Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs index ca161aa..eb2e944 100644 --- a/Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs +++ b/Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs @@ -3,8 +3,8 @@ using MassTransit.Courier.Contracts; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts.Infrastructure; using Musify.Application.Configuration; -using Musify.Infrastructure.MassTransit.Activities.Files; using Musify.Infrastructure.MassTransit.Activities.Arguments; +using Musify.Infrastructure.MassTransit.Activities.Files; using Musify.Infrastructure.MassTransit.Activities.Tracks; using Musify.Infrastructure.MassTransit.Consumers; @@ -42,7 +42,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders var bucket = storageConfiguration.Bucket; routingSlipBuilder.AddActivity( - "RemoveTrackOriginalPicture", + ActivityNames.RemoveTrackOriginalPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, @@ -51,21 +51,21 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders if (track.IsPicturesProcessed) { routingSlipBuilder.AddActivity( - "RemoveTrackSmallPicture", + ActivityNames.RemoveTrackSmallPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, trackConfiguration.Routes.BuildSmallPicturePath(track.SmallPictureName))); routingSlipBuilder.AddActivity( - "RemoveTrackMediumPicture", + ActivityNames.RemoveTrackMediumPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, trackConfiguration.Routes.BuildMediumPicturePath(track.MediumPictureName))); routingSlipBuilder.AddActivity( - "RemoveTrackLargePicture", + ActivityNames.RemoveTrackLargePicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, @@ -73,7 +73,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders } routingSlipBuilder.AddActivity( - "RemoveTrackOriginalAudio", + ActivityNames.RemoveTrackOriginalAudio, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, @@ -82,7 +82,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders if (track.IsAudioProcessed) { routingSlipBuilder.AddActivity( - "RemoveTrackProcessedAudio", + ActivityNames.RemoveTrackProcessedAudio, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, diff --git a/Infrastructure/MassTransit/RoutingSlip/Builders/PlayListPictureSourceRoutingSlipBuilder.cs b/Infrastructure/MassTransit/RoutingSlip/Builders/PlayListPictureSourceRoutingSlipBuilder.cs new file mode 100644 index 0000000..80cf5c2 --- /dev/null +++ b/Infrastructure/MassTransit/RoutingSlip/Builders/PlayListPictureSourceRoutingSlipBuilder.cs @@ -0,0 +1,84 @@ +using MassTransit; +using MassTransit.Courier.Contracts; +using Musify.Application.Events; +using Musify.Infrastructure.MassTransit.Activities.Files; +using Musify.Infrastructure.MassTransit.Activities.PlayLists; +using Musify.Infrastructure.MassTransit.Activities.UploadIntents; +using Musify.Infrastructure.MassTransit.Arguments; +using Musify.Infrastructure.MassTransit.Consumers; + +namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders +{ + public class PlayListPictureSourceRoutingSlipBuilder + { + public RoutingSlipBuilder Build(CreatePlayListResourcesEvent message, Guid? correlationId) + => BuildSlip( + message.PlayListId, + message.PictureIntentId, + message.Bucket, + message.PictureSourceKey, + message.PictureDestinationKey, + message.Small, + message.Medium, + message.Large, + correlationId); + + public RoutingSlipBuilder Build(UpdatePlayListPictureSourceEvent message, Guid? correlationId) + => BuildSlip( + message.PlayListId, + message.PictureIntentId, + message.Bucket, + message.PictureSourceKey, + message.PictureDestinationKey, + message.Small, + message.Medium, + message.Large, + correlationId); + + static RoutingSlipBuilder BuildSlip( + Guid playListId, + Guid pictureIntentId, + string bucket, + string pictureSourceKey, + string pictureDestinationKey, + ImageSize small, + ImageSize medium, + ImageSize large, + Guid? correlationId) + { + var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid()); + routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty); + + routingSlipBuilder.AddSubscription( + EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName), + RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted); + + routingSlipBuilder.AddActivity( + ActivityNames.CopyPictureToFinal, + EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName), + new CopyFileInBucketArguments( + bucket, + pictureSourceKey, + bucket, + pictureDestinationKey)); + + routingSlipBuilder.AddActivity( + ActivityNames.ConsumeUploadIntents, + EndpointHelper.BuildExecuteActivityUri(ConsumeUploadIntentsActivity.ExecuteEndpointName), + new ConsumeUploadIntentsArguments([pictureIntentId])); + + routingSlipBuilder.AddActivity( + ActivityNames.PublishPlayListPictureProcessingEvent, + EndpointHelper.BuildExecuteActivityUri(PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName), + new PublishPlayListPictureProcessingEventArguments( + playListId, + bucket, + pictureDestinationKey, + small, + medium, + large)); + + return routingSlipBuilder; + } + } +} diff --git a/Infrastructure/MassTransit/RoutingSlip/Variables/RoutingSlipVariableNames.cs b/Infrastructure/MassTransit/RoutingSlip/Variables/RoutingSlipVariableNames.cs index 5392816..2667a18 100644 --- a/Infrastructure/MassTransit/RoutingSlip/Variables/RoutingSlipVariableNames.cs +++ b/Infrastructure/MassTransit/RoutingSlip/Variables/RoutingSlipVariableNames.cs @@ -11,9 +11,7 @@ namespace Musify.Infrastructure.MassTransit internal static class Audio { internal const string SourceFilePath = "Audio.SourceFilePath"; - internal const string WorkingDirectory = "Audio.WorkingDirectory"; internal const string TranscodedDirectory = "Audio.TranscodedDirectory"; - internal const string PreviousAudioFolderName = "Audio.PreviousAudioFolderName"; } internal static class Picture @@ -22,7 +20,6 @@ namespace Musify.Infrastructure.MassTransit internal const string SmallResizedFilePath = "Picture.SmallResizedFilePath"; internal const string MediumResizedFilePath = "Picture.MediumResizedFilePath"; internal const string LargeResizedFilePath = "Picture.LargeResizedFilePath"; - internal const string DestinationFolderName = "Picture.DestinationFolderName"; } } }