This commit is contained in:
2026-03-20 20:24:10 +01:00
parent c378c7a0dd
commit 61f4435cc2
7 changed files with 134 additions and 115 deletions
@@ -11,8 +11,7 @@ namespace Musify.Infrastructure.Configuration
serviceDescriptors
.AddValidatedConfiguration<DatabaseConfiguration>(configuration, DatabaseConfiguration.SectionName)
.AddValidatedConfiguration<KeycloakConfiguration>(configuration, KeycloakConfiguration.SectionName)
.AddValidatedConfiguration<StorageClientConfiguration>(configuration, StorageClientConfiguration.SectionName)
.AddValidatedConfiguration<WorkerStorageConfiguration>(configuration, WorkerStorageConfiguration.SectionName);
.AddValidatedConfiguration<StorageClientConfiguration>(configuration, StorageClientConfiguration.SectionName);
return serviceDescriptors;
}
@@ -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";
}
}
@@ -6,24 +6,27 @@ using Musify.Infrastructure.Messaging.Activities.Arguments;
namespace Musify.Infrastructure.Messaging.Activities
{
public class RemoveFilesActivity(IStorageHandler storageHandler, ILogger<RemoveFilesActivity> logger)
: IExecuteActivity<RemoveFileArguments[]>
: IExecuteActivity<RemoveFileArguments>
{
public async Task<ExecutionResult> Execute(ExecuteContext<RemoveFileArguments[]> executeContext)
{
foreach (var file in executeContext.Arguments)
public const string ExecuteEndpointName = "Remove-File";
public async Task<ExecutionResult> Execute(ExecuteContext<RemoveFileArguments> executeContext)
{
var removeFile = await storageHandler.RemoveFileAsync(
file.BucketName,
file.KeyName,
executeContext.Arguments.BucketName,
executeContext.Arguments.KeyName,
executeContext.CancellationToken);
if (!removeFile.IsSuccess)
{
string errorMessage = string.Join(";", removeFile.Errors);
logger.LogWarning("Failed to remove file {File} from bucket {BucketName}: {ErrorMessage}",
file, file.BucketName, errorMessage);
}
logger.LogWarning(
"Failed to remove file {KeyName} from bucket {BucketName}: {ErrorMessage}",
executeContext.Arguments.KeyName,
executeContext.Arguments.BucketName,
errorMessage);
}
return executeContext.Completed();
}
}
@@ -7,6 +7,8 @@ namespace Musify.Infrastructure.Messaging.Activities
public class ResizePictureActivity(IStorageHandler storageHandler, IPictureHandler pictureHandler)
: IExecuteActivity<ResizePictureArgument>
{
public const string ExecuteEndpointName = "Resize-Picture";
public async Task<ExecutionResult> Execute(ExecuteContext<ResizePictureArgument> executeContext)
{
var file = await storageHandler.GetFileAsync(
@@ -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<UpdatePlayListPictureArguments>
{
public const string ExecuteEndpointName = "Update-PlayList-Picture";
public async Task<ExecutionResult> Execute(ExecuteContext<UpdatePlayListPictureArguments> 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();
@@ -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,
smallPictureKeyName,
playListConfiguration.PicturesSizes.SmallPictureWidth,
playListConfiguration.PicturesSizes.SmallPictureHeight));
playListConfiguration.PicturesSizes.SmallPictureHeight,
consumeContext.Message.OriginalPictureKeyName);
routingSlipBuilder.AddActivity(
AddResizeActivity(
routingSlipBuilder,
"ResizeMedium",
new Uri("Queue:Resize-Picture_Execute"),
new ResizePictureArgument(
storageSettings.BucketName,
consumeContext.Message.OriginalPictureKeyName,
storageSettings.BucketName,
playListConfiguration.Routes.MediumPictures,
mediumPictureKeyName,
playListConfiguration.PicturesSizes.MediumPictureWidth,
playListConfiguration.PicturesSizes.MediumPictureHeight));
playListConfiguration.PicturesSizes.MediumPictureHeight,
consumeContext.Message.OriginalPictureKeyName);
routingSlipBuilder.AddActivity(
AddResizeActivity(
routingSlipBuilder,
"ResizeLarge",
new Uri("Queue:Resize-Picture_Execute"),
new ResizePictureArgument(
storageSettings.BucketName,
consumeContext.Message.OriginalPictureKeyName,
storageSettings.BucketName,
playListConfiguration.Routes.LargePictures,
largePictureKeyName,
playListConfiguration.PicturesSizes.LargePictureWidth,
playListConfiguration.PicturesSizes.LargePictureHeight));
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");
}
}
@@ -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,8 +25,40 @@ namespace Musify.Infrastructure.Messaging
serviceDescriptors.AddMassTransit(options =>
{
options.AddConsumer<UpdatePlayListPictureConsumer>();
options.AddExecuteActivity<ResizePictureActivity, ResizePictureArgument>();
options.AddExecuteActivity<RemoveFilesActivity, RemoveFileArguments>();
options.AddExecuteActivity<UpdatePlayListPictureActivity, UpdatePlayListPictureArguments>();
options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) =>
{
ConfigureRabbitMqHost(busFactoryConfigurator, configuration);
busFactoryConfigurator.ReceiveEndpoint(UpdatePlayListPictureConsumer.QueueName, endpointConfigurator =>
{
endpointConfigurator.ConfigureConsumer<UpdatePlayListPictureConsumer>(busRegistrationContext);
} );
ConfigureExecuteActivityEndpoint<ResizePictureActivity, ResizePictureArgument>(
busFactoryConfigurator,
busRegistrationContext,
ResizePictureActivity.ExecuteEndpointName);
ConfigureExecuteActivityEndpoint<RemoveFilesActivity, RemoveFileArguments>(
busFactoryConfigurator,
busRegistrationContext,
RemoveFilesActivity.ExecuteEndpointName);
ConfigureExecuteActivityEndpoint<UpdatePlayListPictureActivity, UpdatePlayListPictureArguments>(
busFactoryConfigurator,
busRegistrationContext,
UpdatePlayListPictureActivity.ExecuteEndpointName);
} );
} );
return serviceDescriptors;
}
static void ConfigureRabbitMqHost(IRabbitMqBusFactoryConfigurator busFactoryConfigurator, IConfiguration configuration)
{
var section = configuration.GetSection("MassTransit");
@@ -58,15 +76,19 @@ namespace Musify.Infrastructure.Messaging
options.Username(username);
options.Password(password);
} );
}
busFactoryConfigurator.ReceiveEndpoint(UpdatePlayListPictureConsumer.QueueName, endpointConfigurator =>
static void ConfigureExecuteActivityEndpoint<TActivity, TArguments>(
IRabbitMqBusFactoryConfigurator busFactoryConfigurator,
IBusRegistrationContext busRegistrationContext,
string endpointName)
where TActivity : class, IExecuteActivity<TArguments>
where TArguments : class
{
endpointConfigurator.ConfigureConsumer<UpdatePlayListPictureConsumer>(busRegistrationContext);
busFactoryConfigurator.ReceiveEndpoint($"{endpointName}_execute", endpointConfigurator =>
{
endpointConfigurator.ExecuteActivityHost<TActivity, TArguments>(busRegistrationContext);
} );
} );
} );
return serviceDescriptors;
}
}
}