From 61f4435cc22367e7b58f5f26e17b65db5f2b17bc Mon Sep 17 00:00:00 2001 From: XShine555 Date: Fri, 20 Mar 2026 20:24:10 +0100 Subject: [PATCH] Refactor --- .../ConfigurationDependencyInjection.cs | 3 +- .../WorkerStorageConfiguration.cs | 21 ----- .../Activities/RemoveFilesActivity.cs | 33 ++++--- .../Activities/ResizePictureActivity.cs | 2 + .../UpdatePlayListPictureActivity.cs | 18 ++-- .../UpdatePlayListPictureConsumer.cs | 80 +++++++++------- .../MassTransitDependencyInjection.cs | 92 ++++++++++++------- 7 files changed, 134 insertions(+), 115 deletions(-) delete mode 100644 Infrastructure/Configuration/WorkerStorageConfiguration.cs diff --git a/Infrastructure/Configuration/ConfigurationDependencyInjection.cs b/Infrastructure/Configuration/ConfigurationDependencyInjection.cs index 50f54bf..a357138 100644 --- a/Infrastructure/Configuration/ConfigurationDependencyInjection.cs +++ b/Infrastructure/Configuration/ConfigurationDependencyInjection.cs @@ -11,8 +11,7 @@ namespace Musify.Infrastructure.Configuration serviceDescriptors .AddValidatedConfiguration(configuration, DatabaseConfiguration.SectionName) .AddValidatedConfiguration(configuration, KeycloakConfiguration.SectionName) - .AddValidatedConfiguration(configuration, StorageClientConfiguration.SectionName) - .AddValidatedConfiguration(configuration, WorkerStorageConfiguration.SectionName); + .AddValidatedConfiguration(configuration, StorageClientConfiguration.SectionName); return serviceDescriptors; } diff --git a/Infrastructure/Configuration/WorkerStorageConfiguration.cs b/Infrastructure/Configuration/WorkerStorageConfiguration.cs deleted file mode 100644 index 6b556e1..0000000 --- a/Infrastructure/Configuration/WorkerStorageConfiguration.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Musify.Infrastructure.Configuration -{ - public class WorkerStorageConfiguration - { - public const string SectionName = "WorkerStorage"; - - public Routes Routes { get; set; } = new Routes(); - - [Required] - [MinLength(3)] - public required string BucketName { get; set; } - } - - public class Routes - { - [Required] - public string TemporaryFiles { get; set; } = "TemporaryFiles"; - } -} diff --git a/Infrastructure/Messaging/Activities/RemoveFilesActivity.cs b/Infrastructure/Messaging/Activities/RemoveFilesActivity.cs index ef53c37..4a4479d 100644 --- a/Infrastructure/Messaging/Activities/RemoveFilesActivity.cs +++ b/Infrastructure/Messaging/Activities/RemoveFilesActivity.cs @@ -6,24 +6,27 @@ using Musify.Infrastructure.Messaging.Activities.Arguments; namespace Musify.Infrastructure.Messaging.Activities { public class RemoveFilesActivity(IStorageHandler storageHandler, ILogger logger) - : IExecuteActivity + : IExecuteActivity { - public async Task Execute(ExecuteContext executeContext) - { - foreach (var file in executeContext.Arguments) - { - var removeFile = await storageHandler.RemoveFileAsync( - file.BucketName, - file.KeyName, - executeContext.CancellationToken); + public const string ExecuteEndpointName = "Remove-File"; - if (!removeFile.IsSuccess) - { - string errorMessage = string.Join(";", removeFile.Errors); - logger.LogWarning("Failed to remove file {File} from bucket {BucketName}: {ErrorMessage}", - file, file.BucketName, errorMessage); - } + public async Task Execute(ExecuteContext executeContext) + { + var removeFile = await storageHandler.RemoveFileAsync( + executeContext.Arguments.BucketName, + executeContext.Arguments.KeyName, + executeContext.CancellationToken); + + if (!removeFile.IsSuccess) + { + string errorMessage = string.Join(";", removeFile.Errors); + logger.LogWarning( + "Failed to remove file {KeyName} from bucket {BucketName}: {ErrorMessage}", + executeContext.Arguments.KeyName, + executeContext.Arguments.BucketName, + errorMessage); } + return executeContext.Completed(); } } diff --git a/Infrastructure/Messaging/Activities/ResizePictureActivity.cs b/Infrastructure/Messaging/Activities/ResizePictureActivity.cs index 868a02b..5e75db4 100644 --- a/Infrastructure/Messaging/Activities/ResizePictureActivity.cs +++ b/Infrastructure/Messaging/Activities/ResizePictureActivity.cs @@ -7,6 +7,8 @@ namespace Musify.Infrastructure.Messaging.Activities public class ResizePictureActivity(IStorageHandler storageHandler, IPictureHandler pictureHandler) : IExecuteActivity { + public const string ExecuteEndpointName = "Resize-Picture"; + public async Task Execute(ExecuteContext executeContext) { var file = await storageHandler.GetFileAsync( diff --git a/Infrastructure/Messaging/Activities/UpdatePlayListPictureActivity.cs b/Infrastructure/Messaging/Activities/UpdatePlayListPictureActivity.cs index 2266ba1..0d5ea4b 100644 --- a/Infrastructure/Messaging/Activities/UpdatePlayListPictureActivity.cs +++ b/Infrastructure/Messaging/Activities/UpdatePlayListPictureActivity.cs @@ -1,4 +1,5 @@ using MassTransit; +using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts.Infrastructure; using Musify.Infrastructure.Messaging.Activities.Arguments; @@ -7,20 +8,21 @@ namespace Musify.Infrastructure.Messaging.Activities public class UpdatePlayListPictureActivity(IDatabase database) : IExecuteActivity { + public const string ExecuteEndpointName = "Update-PlayList-Picture"; + public async Task Execute(ExecuteContext executeContext) { - var PlayList = await database.PlayLists.FindAsync(executeContext.Arguments.PlayListId); + var playList = await database.PlayLists.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, + executeContext.CancellationToken); - if (PlayList is null) - { + if (playList is null) throw new Exception($"PlayList with id {executeContext.Arguments.PlayListId} not found."); - } - PlayList.SmallPictureKeyName = executeContext.Arguments.SmallPictureKeyName; - PlayList.MediumPictureKeyName = executeContext.Arguments.MediumPictureKeyName; - PlayList.LargePictureKeyName = executeContext.Arguments.LargePictureKeyName; + playList.SmallPictureKeyName = executeContext.Arguments.SmallPictureKeyName; + playList.MediumPictureKeyName = executeContext.Arguments.MediumPictureKeyName; + playList.LargePictureKeyName = executeContext.Arguments.LargePictureKeyName; - database.PlayLists.Update(PlayList); + database.PlayLists.Update(playList); await database.SaveChangesAsync(executeContext.CancellationToken); return executeContext.Completed(); diff --git a/Infrastructure/Messaging/Consumers/UpdatePlayListPictureConsumer.cs b/Infrastructure/Messaging/Consumers/UpdatePlayListPictureConsumer.cs index e3e6ada..5f5a57a 100644 --- a/Infrastructure/Messaging/Consumers/UpdatePlayListPictureConsumer.cs +++ b/Infrastructure/Messaging/Consumers/UpdatePlayListPictureConsumer.cs @@ -2,6 +2,7 @@ using Musify.Application.Configuration; using Musify.Application.Contracts.Infrastructure; using Musify.Application.Events; +using Musify.Infrastructure.Messaging.Activities; using Musify.Infrastructure.Messaging.Activities.Arguments; namespace Musify.Infrastructure.Messaging.Consumers @@ -26,49 +27,38 @@ namespace Musify.Infrastructure.Messaging.Consumers playListConfiguration.Routes.LargePictures, $"{consumeContext.Message.PlayListId}_large.{pictureHandler.FileExtension}"); - routingSlipBuilder.AddActivity( + AddResizeActivity( + routingSlipBuilder, "ResizeSmall", - new Uri("Queue:Resize-Picture_Execute"), - new ResizePictureArgument( - storageSettings.BucketName, - consumeContext.Message.OriginalPictureKeyName, - storageSettings.BucketName, - playListConfiguration.Routes.SmallPictures, - playListConfiguration.PicturesSizes.SmallPictureWidth, - playListConfiguration.PicturesSizes.SmallPictureHeight)); - - routingSlipBuilder.AddActivity( - "ResizeMedium", - new Uri("Queue:Resize-Picture_Execute"), - new ResizePictureArgument( - storageSettings.BucketName, - consumeContext.Message.OriginalPictureKeyName, - storageSettings.BucketName, - playListConfiguration.Routes.MediumPictures, - playListConfiguration.PicturesSizes.MediumPictureWidth, - playListConfiguration.PicturesSizes.MediumPictureHeight)); + smallPictureKeyName, + playListConfiguration.PicturesSizes.SmallPictureWidth, + playListConfiguration.PicturesSizes.SmallPictureHeight, + consumeContext.Message.OriginalPictureKeyName); - routingSlipBuilder.AddActivity( + AddResizeActivity( + routingSlipBuilder, + "ResizeMedium", + mediumPictureKeyName, + playListConfiguration.PicturesSizes.MediumPictureWidth, + playListConfiguration.PicturesSizes.MediumPictureHeight, + consumeContext.Message.OriginalPictureKeyName); + + AddResizeActivity( + routingSlipBuilder, "ResizeLarge", - new Uri("Queue:Resize-Picture_Execute"), - new ResizePictureArgument( - storageSettings.BucketName, - consumeContext.Message.OriginalPictureKeyName, - storageSettings.BucketName, - playListConfiguration.Routes.LargePictures, - playListConfiguration.PicturesSizes.LargePictureWidth, - playListConfiguration.PicturesSizes.LargePictureHeight)); + largePictureKeyName, + playListConfiguration.PicturesSizes.LargePictureWidth, + playListConfiguration.PicturesSizes.LargePictureHeight, + consumeContext.Message.OriginalPictureKeyName); routingSlipBuilder.AddActivity( "DeleteOriginal", - new Uri("Queue:Delete-Picture_Execute"), - new RemoveFileArguments( - storageSettings.BucketName, - consumeContext.Message.OriginalPictureKeyName)); + BuildExecuteUri(RemoveFilesActivity.ExecuteEndpointName), + new RemoveFileArguments(storageSettings.BucketName, consumeContext.Message.OriginalPictureKeyName)); routingSlipBuilder.AddActivity( "UpdatePlayListPicture", - new Uri("Queue:Update-PlayList-Picture_Execute"), + BuildExecuteUri(UpdatePlayListPictureActivity.ExecuteEndpointName), new UpdatePlayListPictureArguments( consumeContext.Message.PlayListId, smallPictureKeyName, @@ -78,5 +68,27 @@ namespace Musify.Infrastructure.Messaging.Consumers var routingSlip = routingSlipBuilder.Build(); await bus.Execute(routingSlip); } + + void AddResizeActivity( + RoutingSlipBuilder routingSlipBuilder, + string activityName, + string destinationKeyName, + int width, + int height, + string originalPictureKeyName) + { + routingSlipBuilder.AddActivity( + activityName, + BuildExecuteUri(ResizePictureActivity.ExecuteEndpointName), + new ResizePictureArgument( + storageSettings.BucketName, + originalPictureKeyName, + storageSettings.BucketName, + destinationKeyName, + width, + height)); + } + + static Uri BuildExecuteUri(string endpointName) => new($"queue:{endpointName}_execute"); } } \ No newline at end of file diff --git a/Infrastructure/Messaging/MassTransitDependencyInjection.cs b/Infrastructure/Messaging/MassTransitDependencyInjection.cs index f44ddcf..d2e843e 100644 --- a/Infrastructure/Messaging/MassTransitDependencyInjection.cs +++ b/Infrastructure/Messaging/MassTransitDependencyInjection.cs @@ -1,6 +1,8 @@ using MassTransit; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Musify.Infrastructure.Messaging.Activities; +using Musify.Infrastructure.Messaging.Activities.Arguments; using Musify.Infrastructure.Messaging.Consumers; namespace Musify.Infrastructure.Messaging @@ -11,26 +13,10 @@ namespace Musify.Infrastructure.Messaging { serviceDescriptors.AddMassTransit(options => { - options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) => - { - var section = configuration.GetSection("MassTransit"); - - var host = section["Host"] - ?? throw new InvalidOperationException("MassTransit:Host configuration value not found."); - - var username = section["Username"] - ?? throw new InvalidOperationException("MassTransit:Username configuration value not found."); - - var password = section["Password"] - ?? throw new InvalidOperationException("MassTransit:Password configuration value not found."); - - busFactoryConfigurator.Host(host, options => - { - options.Username(username); - options.Password(password); - } ); - } ); + options.UsingRabbitMq((_, busFactoryConfigurator) => + ConfigureRabbitMqHost(busFactoryConfigurator, configuration)); } ); + return serviceDescriptors; } @@ -39,34 +25,70 @@ namespace Musify.Infrastructure.Messaging serviceDescriptors.AddMassTransit(options => { options.AddConsumer(); + options.AddExecuteActivity(); + options.AddExecuteActivity(); + options.AddExecuteActivity(); options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) => { - var section = configuration.GetSection("MassTransit"); - - var host = section["Host"] - ?? throw new InvalidOperationException("MassTransit:Host configuration value not found."); - - var username = section["Username"] - ?? throw new InvalidOperationException("MassTransit:Username configuration value not found."); - - var password = section["Password"] - ?? throw new InvalidOperationException("MassTransit:Password configuration value not found."); - - busFactoryConfigurator.Host(host, options => - { - options.Username(username); - options.Password(password); - } ); + ConfigureRabbitMqHost(busFactoryConfigurator, configuration); busFactoryConfigurator.ReceiveEndpoint(UpdatePlayListPictureConsumer.QueueName, endpointConfigurator => { endpointConfigurator.ConfigureConsumer(busRegistrationContext); } ); + + ConfigureExecuteActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + ResizePictureActivity.ExecuteEndpointName); + + ConfigureExecuteActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + RemoveFilesActivity.ExecuteEndpointName); + + ConfigureExecuteActivityEndpoint( + busFactoryConfigurator, + busRegistrationContext, + UpdatePlayListPictureActivity.ExecuteEndpointName); } ); } ); return serviceDescriptors; } + + static void ConfigureRabbitMqHost(IRabbitMqBusFactoryConfigurator busFactoryConfigurator, IConfiguration configuration) + { + var section = configuration.GetSection("MassTransit"); + + var host = section["Host"] + ?? throw new InvalidOperationException("MassTransit:Host configuration value not found."); + + var username = section["Username"] + ?? throw new InvalidOperationException("MassTransit:Username configuration value not found."); + + var password = section["Password"] + ?? throw new InvalidOperationException("MassTransit:Password configuration value not found."); + + busFactoryConfigurator.Host(host, options => + { + options.Username(username); + options.Password(password); + } ); + } + + static void ConfigureExecuteActivityEndpoint( + IRabbitMqBusFactoryConfigurator busFactoryConfigurator, + IBusRegistrationContext busRegistrationContext, + string endpointName) + where TActivity : class, IExecuteActivity + where TArguments : class + { + busFactoryConfigurator.ReceiveEndpoint($"{endpointName}_execute", endpointConfigurator => + { + endpointConfigurator.ExecuteActivityHost(busRegistrationContext); + } ); + } } } \ No newline at end of file