Deduplicate MassTransit routing slips, activities and consumers

This commit is contained in:
2026-09-24 12:25:55 +02:00
parent 0cba32f776
commit 405df082cc
76 changed files with 922 additions and 1933 deletions
@@ -1,37 +1,18 @@
using MassTransit;
using MassTransit.Courier.Contracts;
using Musify.Application.Events;
using Musify.Infrastructure.MassTransit.Activities.Albums;
using Musify.Infrastructure.MassTransit.Activities.Files;
using Musify.Infrastructure.MassTransit.Arguments;
using Musify.Infrastructure.MassTransit.Activities.LifeCycle;
using Musify.Infrastructure.MassTransit.RoutingSlip;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class AlbumProcessingFailedConsumer(IBus bus) : IConsumer<AlbumProcessingFailed>
{
public async Task Consume(ConsumeContext<AlbumProcessingFailed> context)
public Task Consume(ConsumeContext<AlbumProcessingFailed> context)
{
var message = context.Message;
var builder = new RoutingSlipBuilder(NewId.NextGuid());
builder.AddSubscription(
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
if (!string.IsNullOrWhiteSpace(message.Bucket) && !string.IsNullOrWhiteSpace(message.PictureKey))
{
builder.AddActivity(
ActivityNames.RemoveAlbumOriginalPicture,
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
new RemoveFileFromBucketArguments(message.Bucket, message.PictureKey));
}
builder.AddActivity(
ActivityNames.MarkAlbumAsFailed,
EndpointHelper.BuildExecuteActivityUri(MarkAlbumAsFailedActivity.ExecuteEndpointName),
new MarkAlbumAsFailedArguments(message.AlbumId));
await bus.Execute(builder.Build());
return ProcessingFailedCleanup.ExecuteAsync(
bus, message.AlbumId, ActivityNames.MarkAlbumAsFailed, MarkAlbumLifeCycleActivity.ExecuteEndpointName, message.Bucket,
(ActivityNames.RemoveAlbumOriginalPicture, message.PictureKey));
}
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class CreateAlbumConsumer(
IBus bus,
AlbumPictureSourceRoutingSlipBuilder routingSlipBuilder)
public class CreateAlbumConsumer(IBus bus, PictureSourceRoutingSlipBuilder routingSlipBuilder)
: IConsumer<CreateAlbumResourcesEvent>
{
public async Task Consume(ConsumeContext<CreateAlbumResourcesEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<CreateAlbumResourcesEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class CreatePlayListConsumer(
IBus bus,
PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder)
public class CreatePlayListConsumer(IBus bus, PictureSourceRoutingSlipBuilder routingSlipBuilder)
: IConsumer<CreatePlayListResourcesEvent>
{
public async Task Consume(ConsumeContext<CreatePlayListResourcesEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<CreatePlayListResourcesEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class CreateTrackConsumer(
IBus bus,
CreateTrackRoutingSlipBuilder routingSlipBuilder)
public class CreateTrackConsumer(IBus bus, CreateTrackRoutingSlipBuilder routingSlipBuilder)
: IConsumer<CreateTrackResourcesEvent>
{
public async Task Consume(ConsumeContext<CreateTrackResourcesEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<CreateTrackResourcesEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,21 +4,15 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class DeleteAlbumConsumer(
IBus bus,
DeleteAlbumRoutingSlipBuilder routingSlipBuilder)
public class DeleteAlbumConsumer(IBus bus, DeleteRoutingSlipBuilder routingSlipBuilder)
: IConsumer<DeleteAlbumEvent>
{
public async Task Consume(ConsumeContext<DeleteAlbumEvent> consumeContext)
public async Task Consume(ConsumeContext<DeleteAlbumEvent> context)
{
var routingSlip = (await routingSlipBuilder
.BuildAsync(
consumeContext.Message.AlbumId,
consumeContext.Message.UserId,
consumeContext.CorrelationId,
consumeContext.CancellationToken))
.Build();
var message = context.Message;
var routingSlip = await routingSlipBuilder.BuildAlbumAsync(
message.AlbumId, message.UserId, context.CorrelationId, context.CancellationToken);
await bus.Execute(routingSlip);
await bus.Execute(routingSlip.Build());
}
}
@@ -4,21 +4,15 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class DeletePlayListConsumer(
IBus bus,
DeletePlayListRoutingSlipBuilder routingSlipBuilder)
public class DeletePlayListConsumer(IBus bus, DeleteRoutingSlipBuilder routingSlipBuilder)
: IConsumer<DeletePlayListEvent>
{
public async Task Consume(ConsumeContext<DeletePlayListEvent> consumeContext)
public async Task Consume(ConsumeContext<DeletePlayListEvent> context)
{
var routingSlip = (await routingSlipBuilder
.BuildAsync(
consumeContext.Message.PlayListId,
consumeContext.Message.UserId,
consumeContext.CorrelationId,
consumeContext.CancellationToken))
.Build();
var message = context.Message;
var routingSlip = await routingSlipBuilder.BuildPlayListAsync(
message.PlayListId, message.UserId, context.CorrelationId, context.CancellationToken);
await bus.Execute(routingSlip);
await bus.Execute(routingSlip.Build());
}
}
@@ -4,17 +4,15 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class DeleteTrackConsumer(
IBus bus,
DeleteTrackRoutingSlipBuilder routingSlipBuilder)
public class DeleteTrackConsumer(IBus bus, DeleteRoutingSlipBuilder routingSlipBuilder)
: IConsumer<DeleteTrackEvent>
{
public async Task Consume(ConsumeContext<DeleteTrackEvent> consumeContext)
public async Task Consume(ConsumeContext<DeleteTrackEvent> context)
{
var routingSlip = (await routingSlipBuilder
.BuildAsync(consumeContext.Message.TrackId, consumeContext.Message.UserId, consumeContext.CorrelationId, consumeContext.CancellationToken))
.Build();
var message = context.Message;
var routingSlip = await routingSlipBuilder.BuildTrackAsync(
message.TrackId, message.UserId, context.CorrelationId, context.CancellationToken);
await bus.Execute(routingSlip);
await bus.Execute(routingSlip.Build());
}
}
@@ -1,8 +0,0 @@
namespace Musify.Infrastructure.MassTransit.Consumers;
internal static class EndpointHelper
{
internal static Uri BuildExecuteActivityUri(string endpointName) => new($"queue:{endpointName}_execute");
internal static Uri BuildConsumerUri(string endpointName) => new($"queue:{endpointName}");
}
@@ -1,37 +1,18 @@
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.Arguments;
using Musify.Infrastructure.MassTransit.Activities.LifeCycle;
using Musify.Infrastructure.MassTransit.RoutingSlip;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class PlayListProcessingFailedConsumer(IBus bus) : IConsumer<PlayListProcessingFailed>
{
public async Task Consume(ConsumeContext<PlayListProcessingFailed> context)
public Task Consume(ConsumeContext<PlayListProcessingFailed> context)
{
var message = context.Message;
var builder = new RoutingSlipBuilder(NewId.NextGuid());
builder.AddSubscription(
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
if (!string.IsNullOrWhiteSpace(message.Bucket) && !string.IsNullOrWhiteSpace(message.PictureKey))
{
builder.AddActivity(
ActivityNames.RemovePlayListOriginalPicture,
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
new RemoveFileFromBucketArguments(message.Bucket, message.PictureKey));
}
builder.AddActivity(
ActivityNames.MarkPlayListAsFailed,
EndpointHelper.BuildExecuteActivityUri(MarkPlayListAsFailedActivity.ExecuteEndpointName),
new MarkPlayListAsFailedArguments(message.PlayListId));
await bus.Execute(builder.Build());
return ProcessingFailedCleanup.ExecuteAsync(
bus, message.PlayListId, ActivityNames.MarkPlayListAsFailed, MarkPlayListLifeCycleActivity.ExecuteEndpointName, message.Bucket,
(ActivityNames.RemovePlayListOriginalPicture, message.PictureKey));
}
}
@@ -0,0 +1,34 @@
using MassTransit;
using Musify.Domain.ValueObjects;
using Musify.Infrastructure.MassTransit.Arguments;
using Musify.Infrastructure.MassTransit.RoutingSlip;
namespace Musify.Infrastructure.MassTransit.Consumers;
internal static class ProcessingFailedCleanup
{
/// <summary>Removes whatever files were left behind and marks the entity as failed.</summary>
public static Task ExecuteAsync(
IBus bus,
Guid subjectId,
string markStepName,
string markEndpointName,
string? bucket,
params (string StepName, string? Key)[] files)
{
var builder = RoutingSlips.Create(correlationId: null);
if (!string.IsNullOrWhiteSpace(bucket))
{
foreach (var (stepName, key) in files)
{
if (!string.IsNullOrWhiteSpace(key))
builder.AddRemoveFile(stepName, bucket, key);
}
}
builder.AddStep(markStepName, markEndpointName, new MarkLifeCycleArguments(subjectId, LifeCycleStatus.Failed));
return bus.Execute(builder.Build());
}
}
@@ -1,6 +1,7 @@
using MassTransit;
using MassTransit.Courier.Contracts;
using Musify.Application.Events;
using Musify.Infrastructure.MassTransit.RoutingSlip;
namespace Musify.Infrastructure.MassTransit.Consumers;
@@ -1,6 +1,7 @@
using MassTransit;
using MassTransit.Courier.Contracts;
using Microsoft.Extensions.Logging;
using Musify.Infrastructure.MassTransit.RoutingSlip;
namespace Musify.Infrastructure.MassTransit.Consumers;
@@ -32,14 +33,9 @@ public class RoutingSlipCleanUpConsumer(
Directory.Delete(pathString, recursive: true);
logger.LogInformation("Deleted temporal directory at path {Path}", pathString);
}
catch (DirectoryNotFoundException directoryNotFoundException)
catch (DirectoryNotFoundException)
{
logger.LogWarning(directoryNotFoundException, "Temporal directory at path {Path} was not found for deletion", pathString);
}
catch (Exception exception)
{
logger.LogError(exception, "Failed to delete temporal directory at path {Path}", pathString);
throw;
logger.LogWarning("Temporal directory at path {Path} was not found for deletion", pathString);
}
return Task.CompletedTask;
@@ -1,45 +1,19 @@
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.Arguments;
using Musify.Infrastructure.MassTransit.Activities.LifeCycle;
using Musify.Infrastructure.MassTransit.RoutingSlip;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class TrackProcessingFailedConsumer(IBus bus) : IConsumer<TrackProcessingFailed>
{
public async Task Consume(ConsumeContext<TrackProcessingFailed> context)
public Task Consume(ConsumeContext<TrackProcessingFailed> context)
{
var message = context.Message;
var builder = new RoutingSlipBuilder(NewId.NextGuid());
builder.AddSubscription(
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
if (!string.IsNullOrWhiteSpace(message.Bucket) && !string.IsNullOrWhiteSpace(message.PictureKey))
{
builder.AddActivity(
ActivityNames.RemoveTrackOriginalPicture,
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
new RemoveFileFromBucketArguments(message.Bucket, message.PictureKey));
}
if (!string.IsNullOrWhiteSpace(message.Bucket) && !string.IsNullOrWhiteSpace(message.AudioKey))
{
builder.AddActivity(
ActivityNames.RemoveTrackOriginalAudio,
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
new RemoveFileFromBucketArguments(message.Bucket, message.AudioKey));
}
builder.AddActivity(
ActivityNames.MarkTrackAsFailed,
EndpointHelper.BuildExecuteActivityUri(MarkTrackAsFailedActivity.ExecuteEndpointName),
new MarkTrackAsFailedArguments(message.TrackId));
await bus.Execute(builder.Build());
return ProcessingFailedCleanup.ExecuteAsync(
bus, message.TrackId, ActivityNames.MarkTrackAsFailed, MarkTrackLifeCycleActivity.ExecuteEndpointName, message.Bucket,
(ActivityNames.RemoveTrackOriginalPicture, message.PictureKey),
(ActivityNames.RemoveTrackOriginalAudio, message.AudioKey));
}
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class UpdateAlbumPictureConsumer(
IBus bus,
PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
public class UpdateAlbumPictureConsumer(IBus bus, PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
: IConsumer<UpdateAlbumPictureEvent>
{
public async Task Consume(ConsumeContext<UpdateAlbumPictureEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<UpdateAlbumPictureEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class UpdateAlbumPictureSourceConsumer(
IBus bus,
AlbumPictureSourceRoutingSlipBuilder routingSlipBuilder)
public class UpdateAlbumPictureSourceConsumer(IBus bus, PictureSourceRoutingSlipBuilder routingSlipBuilder)
: IConsumer<UpdateAlbumPictureSourceEvent>
{
public async Task Consume(ConsumeContext<UpdateAlbumPictureSourceEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<UpdateAlbumPictureSourceEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class UpdatePlayListPictureConsumer(
IBus bus,
PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
public class UpdatePlayListPictureConsumer(IBus bus, PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
: IConsumer<UpdatePlayListPictureEvent>
{
public async Task Consume(ConsumeContext<UpdatePlayListPictureEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<UpdatePlayListPictureEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class UpdatePlayListPictureSourceConsumer(
IBus bus,
PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder)
public class UpdatePlayListPictureSourceConsumer(IBus bus, PictureSourceRoutingSlipBuilder routingSlipBuilder)
: IConsumer<UpdatePlayListPictureSourceEvent>
{
public async Task Consume(ConsumeContext<UpdatePlayListPictureSourceEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<UpdatePlayListPictureSourceEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class UpdateTrackAudioConsumer(
IBus bus,
AudioWorkflowRoutingSlipBuilder routingSlipBuilder)
public class UpdateTrackAudioConsumer(IBus bus, AudioWorkflowRoutingSlipBuilder routingSlipBuilder)
: IConsumer<UpdateTrackAudioEvent>
{
public async Task Consume(ConsumeContext<UpdateTrackAudioEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<UpdateTrackAudioEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}
@@ -4,17 +4,9 @@ using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
namespace Musify.Infrastructure.MassTransit.Consumers;
public class UpdateTrackPictureConsumer(
IBus bus,
PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
public class UpdateTrackPictureConsumer(IBus bus, PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
: IConsumer<UpdateTrackPictureEvent>
{
public async Task Consume(ConsumeContext<UpdateTrackPictureEvent> consumeContext)
{
var routingSlip = routingSlipBuilder
.Build(consumeContext.Message, consumeContext.CorrelationId)
.Build();
await bus.Execute(routingSlip);
}
public Task Consume(ConsumeContext<UpdateTrackPictureEvent> context) =>
bus.Execute(routingSlipBuilder.Build(context.Message, context.CorrelationId).Build());
}