Change editor rule

This commit is contained in:
2026-09-24 13:24:43 +02:00
parent 16478678b5
commit 73e37dbecd
401 changed files with 14735 additions and 12995 deletions
@@ -5,40 +5,41 @@ using Musify.Infrastructure.MassTransit.Activities.Audio;
using Musify.Infrastructure.MassTransit.Activities.Files;
using Musify.Infrastructure.MassTransit.Arguments;
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
public class AudioWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
{
public RoutingSlipBuilder Build(UpdateTrackAudioEvent message, Guid? correlationId) =>
RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.GenerateAudioWorkflowPaths,
GenerateAudioWorkflowPathsActivity.ExecuteEndpointName,
new GenerateAudioWorkflowPathsArguments(
message.TrackId, workerConfiguration.Routes.TemporaryFilesDirectory, message.SourceKey))
.AddStep(
ActivityNames.DownloadFile,
DownloadFileFromBucketActivity.ExecuteEndpointName,
new DownloadFileFromBucketArguments(
message.SourceBucket, message.SourceKey, RoutingSlipVariableNames.Audio.SourceFilePath))
.AddStep(
ActivityNames.TranscodeAudio,
TranscodeAudioActivity.ExecuteEndpointName,
new TranscodeAudioArguments(
message.TrackId,
RoutingSlipVariableNames.Audio.SourceFilePath,
RoutingSlipVariableNames.Workflow.TemporalDirectory))
.AddStep(
ActivityNames.TransferFiles,
TransferFilesToBucketActivity.ExecuteEndpointName,
new TransferFilesToBucketArguments(
message.DestinationBucket,
RoutingSlipVariableNames.Audio.TranscodedDirectory,
message.DestinationFolderKey))
.AddStep(
ActivityNames.UpdateTrackAudio,
UpdateTrackAudioActivity.ExecuteEndpointName,
new UpdateTrackAudioArguments(
message.TrackId, message.DestinationFolderKey, RoutingSlipVariableNames.Audio.DurationSeconds))
.TrackFaults(message.TrackId, RoutingSlipVariableNames.ProcessKinds.TrackAudio);
public class AudioWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
{
public RoutingSlipBuilder Build(UpdateTrackAudioEvent message, Guid? correlationId) =>
RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.GenerateAudioWorkflowPaths,
GenerateAudioWorkflowPathsActivity.ExecuteEndpointName,
new GenerateAudioWorkflowPathsArguments(
message.TrackId, workerConfiguration.Routes.TemporaryFilesDirectory, message.SourceKey))
.AddStep(
ActivityNames.DownloadFile,
DownloadFileFromBucketActivity.ExecuteEndpointName,
new DownloadFileFromBucketArguments(
message.SourceBucket, message.SourceKey, RoutingSlipVariableNames.Audio.SourceFilePath))
.AddStep(
ActivityNames.TranscodeAudio,
TranscodeAudioActivity.ExecuteEndpointName,
new TranscodeAudioArguments(
message.TrackId,
RoutingSlipVariableNames.Audio.SourceFilePath,
RoutingSlipVariableNames.Workflow.TemporalDirectory))
.AddStep(
ActivityNames.TransferFiles,
TransferFilesToBucketActivity.ExecuteEndpointName,
new TransferFilesToBucketArguments(
message.DestinationBucket,
RoutingSlipVariableNames.Audio.TranscodedDirectory,
message.DestinationFolderKey))
.AddStep(
ActivityNames.UpdateTrackAudio,
UpdateTrackAudioActivity.ExecuteEndpointName,
new UpdateTrackAudioArguments(
message.TrackId, message.DestinationFolderKey, RoutingSlipVariableNames.Audio.DurationSeconds))
.TrackFaults(message.TrackId, RoutingSlipVariableNames.ProcessKinds.TrackAudio);
}
}
@@ -5,41 +5,42 @@ using Musify.Infrastructure.MassTransit.Activities.Tracks;
using Musify.Infrastructure.MassTransit.Activities.UploadIntents;
using Musify.Infrastructure.MassTransit.Arguments;
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
public class CreateTrackRoutingSlipBuilder
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
{
public RoutingSlipBuilder Build(CreateTrackResourcesEvent message, Guid? correlationId)
public class CreateTrackRoutingSlipBuilder
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.CopyPictureToFinal,
CopyFileInBucketActivity.ExecuteEndpointName,
new CopyFileInBucketArguments(message.Bucket, message.PictureSourceKey, message.Bucket, message.PictureDestinationKey))
.AddStep(
ActivityNames.CopyAudioToFinal,
CopyFileInBucketActivity.ExecuteEndpointName,
new CopyFileInBucketArguments(message.Bucket, message.AudioSourceKey, message.Bucket, message.AudioDestinationKey))
.AddStep(
ActivityNames.ConsumeUploadIntents,
ConsumeUploadIntentsActivity.ExecuteEndpointName,
new ConsumeUploadIntentsArguments([message.PictureIntentId, message.AudioIntentId]))
.AddStep(
ActivityNames.PublishTrackProcessingEvents,
PublishTrackProcessingEventsActivity.ExecuteEndpointName,
new PublishTrackProcessingEventsArguments(
message.TrackId,
message.Bucket,
message.PictureDestinationKey,
message.AudioDestinationKey,
message.AudioProcessedFolderKey,
message.Sizes))
.TrackFaults(message.TrackId, RoutingSlipVariableNames.ProcessKinds.TrackCreation);
public RoutingSlipBuilder Build(CreateTrackResourcesEvent message, Guid? correlationId)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.CopyPictureToFinal,
CopyFileInBucketActivity.ExecuteEndpointName,
new CopyFileInBucketArguments(message.Bucket, message.PictureSourceKey, message.Bucket, message.PictureDestinationKey))
.AddStep(
ActivityNames.CopyAudioToFinal,
CopyFileInBucketActivity.ExecuteEndpointName,
new CopyFileInBucketArguments(message.Bucket, message.AudioSourceKey, message.Bucket, message.AudioDestinationKey))
.AddStep(
ActivityNames.ConsumeUploadIntents,
ConsumeUploadIntentsActivity.ExecuteEndpointName,
new ConsumeUploadIntentsArguments([message.PictureIntentId, message.AudioIntentId]))
.AddStep(
ActivityNames.PublishTrackProcessingEvents,
PublishTrackProcessingEventsActivity.ExecuteEndpointName,
new PublishTrackProcessingEventsArguments(
message.TrackId,
message.Bucket,
message.PictureDestinationKey,
message.AudioDestinationKey,
message.AudioProcessedFolderKey,
message.Sizes))
.TrackFaults(message.TrackId, RoutingSlipVariableNames.ProcessKinds.TrackCreation);
builder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, message.Bucket);
builder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, message.PictureDestinationKey);
builder.AddVariable(RoutingSlipVariableNames.Workflow.AudioKey, message.AudioDestinationKey);
builder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, message.Bucket);
builder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, message.PictureDestinationKey);
builder.AddVariable(RoutingSlipVariableNames.Workflow.AudioKey, message.AudioDestinationKey);
return builder;
return builder;
}
}
}
@@ -6,130 +6,131 @@ using Musify.Domain.ValueObjects;
using Musify.Infrastructure.MassTransit.Activities.LifeCycle;
using Musify.Infrastructure.MassTransit.Arguments;
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
/// <summary>Marks an entity as removing, deletes its files from the bucket and finally deletes its row.</summary>
public class DeleteRoutingSlipBuilder(
IDatabase database,
TrackConfiguration trackConfiguration,
AlbumConfiguration albumConfiguration,
PlayListConfiguration playListConfiguration,
ApplicationStorageConfiguration storageConfiguration)
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
{
private sealed record PictureStepNames(string Original, string Small, string Medium, string Large);
private static readonly PictureStepNames AlbumSteps = new(
ActivityNames.RemoveAlbumOriginalPicture, ActivityNames.RemoveAlbumSmallPicture,
ActivityNames.RemoveAlbumMediumPicture, ActivityNames.RemoveAlbumLargePicture);
private static readonly PictureStepNames PlayListSteps = new(
ActivityNames.RemovePlayListOriginalPicture, ActivityNames.RemovePlayListSmallPicture,
ActivityNames.RemovePlayListMediumPicture, ActivityNames.RemovePlayListLargePicture);
public async Task<RoutingSlipBuilder> BuildTrackAsync(
Guid trackId, long userId, Guid? correlationId, CancellationToken cancellationToken)
/// <summary>Marks an entity as removing, deletes its files from the bucket and finally deletes its row.</summary>
public class DeleteRoutingSlipBuilder(
IDatabase database,
TrackConfiguration trackConfiguration,
AlbumConfiguration albumConfiguration,
PlayListConfiguration playListConfiguration,
ApplicationStorageConfiguration storageConfiguration)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.MarkTrackAsRemoving,
MarkTrackLifeCycleActivity.ExecuteEndpointName,
new MarkLifeCycleArguments(trackId, LifeCycleStatus.Removing));
private sealed record PictureStepNames(string Original, string Small, string Medium, string Large);
var track = await database.Tracks.AsNoTracking().SingleOrDefaultAsync(t => t.Id == trackId, cancellationToken);
if (track != null)
private static readonly PictureStepNames AlbumSteps = new(
ActivityNames.RemoveAlbumOriginalPicture, ActivityNames.RemoveAlbumSmallPicture,
ActivityNames.RemoveAlbumMediumPicture, ActivityNames.RemoveAlbumLargePicture);
private static readonly PictureStepNames PlayListSteps = new(
ActivityNames.RemovePlayListOriginalPicture, ActivityNames.RemovePlayListSmallPicture,
ActivityNames.RemovePlayListMediumPicture, ActivityNames.RemovePlayListLargePicture);
public async Task<RoutingSlipBuilder> BuildTrackAsync(
Guid trackId, long userId, Guid? correlationId, CancellationToken cancellationToken)
{
var bucket = storageConfiguration.Bucket;
var routes = trackConfiguration.Routes;
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.MarkTrackAsRemoving,
MarkTrackLifeCycleActivity.ExecuteEndpointName,
new MarkLifeCycleArguments(trackId, LifeCycleStatus.Removing));
if (!string.IsNullOrEmpty(track.Pictures.OriginalName))
var track = await database.Tracks.AsNoTracking().SingleOrDefaultAsync(t => t.Id == trackId, cancellationToken);
if (track != null)
{
builder.AddRemoveFile(
ActivityNames.RemoveTrackOriginalPicture, bucket,
routes.BuildOriginalPicturePath(userId, track.Pictures.OriginalName));
var bucket = storageConfiguration.Bucket;
var routes = trackConfiguration.Routes;
if (!string.IsNullOrEmpty(track.Pictures.OriginalName))
{
builder.AddRemoveFile(
ActivityNames.RemoveTrackOriginalPicture, bucket,
routes.BuildOriginalPicturePath(userId, track.Pictures.OriginalName));
}
// Unprocessed tracks still point at the shared preset pictures, which must never be deleted.
if (track.Pictures.IsProcessed)
{
builder.AddRemoveFile(ActivityNames.RemoveTrackSmallPicture, bucket, routes.BuildPicturePath(PictureSize.Small, track.Pictures.SmallName));
builder.AddRemoveFile(ActivityNames.RemoveTrackMediumPicture, bucket, routes.BuildPicturePath(PictureSize.Medium, track.Pictures.MediumName));
builder.AddRemoveFile(ActivityNames.RemoveTrackLargePicture, bucket, routes.BuildPicturePath(PictureSize.Large, track.Pictures.LargeName));
}
if (!string.IsNullOrEmpty(track.Audio.OriginalName))
{
builder.AddRemoveFile(
ActivityNames.RemoveTrackOriginalAudio, bucket,
routes.BuildOriginalAudioPath(userId, track.Audio.OriginalName));
}
if (track.Audio.IsProcessed)
{
builder.AddRemoveFile(
ActivityNames.RemoveTrackProcessedAudio, bucket,
routes.BuildProcessedAudioPath(track.Audio.FolderName));
}
}
// Unprocessed tracks still point at the shared preset pictures, which must never be deleted.
if (track.Pictures.IsProcessed)
{
builder.AddRemoveFile(ActivityNames.RemoveTrackSmallPicture, bucket, routes.BuildPicturePath(PictureSize.Small, track.Pictures.SmallName));
builder.AddRemoveFile(ActivityNames.RemoveTrackMediumPicture, bucket, routes.BuildPicturePath(PictureSize.Medium, track.Pictures.MediumName));
builder.AddRemoveFile(ActivityNames.RemoveTrackLargePicture, bucket, routes.BuildPicturePath(PictureSize.Large, track.Pictures.LargeName));
}
if (!string.IsNullOrEmpty(track.Audio.OriginalName))
{
builder.AddRemoveFile(
ActivityNames.RemoveTrackOriginalAudio, bucket,
routes.BuildOriginalAudioPath(userId, track.Audio.OriginalName));
}
if (track.Audio.IsProcessed)
{
builder.AddRemoveFile(
ActivityNames.RemoveTrackProcessedAudio, bucket,
routes.BuildProcessedAudioPath(track.Audio.FolderName));
}
return builder.AddStep(
ActivityNames.DeleteTrackFromDb, DeleteTrackActivity.ExecuteEndpointName, new DeleteEntityArguments(trackId));
}
return builder.AddStep(
ActivityNames.DeleteTrackFromDb, DeleteTrackActivity.ExecuteEndpointName, new DeleteEntityArguments(trackId));
}
public async Task<RoutingSlipBuilder> BuildAlbumAsync(
Guid albumId, long userId, Guid? correlationId, CancellationToken cancellationToken)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.MarkAlbumAsRemoving,
MarkAlbumLifeCycleActivity.ExecuteEndpointName,
new MarkLifeCycleArguments(albumId, LifeCycleStatus.Removing));
public async Task<RoutingSlipBuilder> BuildAlbumAsync(
Guid albumId, long userId, Guid? correlationId, CancellationToken cancellationToken)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.MarkAlbumAsRemoving,
MarkAlbumLifeCycleActivity.ExecuteEndpointName,
new MarkLifeCycleArguments(albumId, LifeCycleStatus.Removing));
var pictures = await database.Albums.AsNoTracking()
.Where(a => a.Id == albumId)
.Select(a => a.Pictures)
.SingleOrDefaultAsync(cancellationToken);
var pictures = await database.Albums.AsNoTracking()
.Where(a => a.Id == albumId)
.Select(a => a.Pictures)
.SingleOrDefaultAsync(cancellationToken);
AddPictureRemovals(builder, AlbumSteps, albumConfiguration.Routes, userId, pictures);
AddPictureRemovals(builder, AlbumSteps, albumConfiguration.Routes, userId, pictures);
return builder.AddStep(
ActivityNames.DeleteAlbumFromDb, DeleteAlbumActivity.ExecuteEndpointName, new DeleteEntityArguments(albumId));
}
return builder.AddStep(
ActivityNames.DeleteAlbumFromDb, DeleteAlbumActivity.ExecuteEndpointName, new DeleteEntityArguments(albumId));
}
public async Task<RoutingSlipBuilder> BuildPlayListAsync(
Guid playListId, long userId, Guid? correlationId, CancellationToken cancellationToken)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.MarkPlayListAsRemoving,
MarkPlayListLifeCycleActivity.ExecuteEndpointName,
new MarkLifeCycleArguments(playListId, LifeCycleStatus.Removing));
public async Task<RoutingSlipBuilder> BuildPlayListAsync(
Guid playListId, long userId, Guid? correlationId, CancellationToken cancellationToken)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.MarkPlayListAsRemoving,
MarkPlayListLifeCycleActivity.ExecuteEndpointName,
new MarkLifeCycleArguments(playListId, LifeCycleStatus.Removing));
var pictures = await database.PlayLists.AsNoTracking()
.Where(p => p.Id == playListId)
.Select(p => p.Pictures)
.SingleOrDefaultAsync(cancellationToken);
var pictures = await database.PlayLists.AsNoTracking()
.Where(p => p.Id == playListId)
.Select(p => p.Pictures)
.SingleOrDefaultAsync(cancellationToken);
AddPictureRemovals(builder, PlayListSteps, playListConfiguration.Routes, userId, pictures);
AddPictureRemovals(builder, PlayListSteps, playListConfiguration.Routes, userId, pictures);
return builder.AddStep(
ActivityNames.DeletePlayListFromDb, DeletePlayListActivity.ExecuteEndpointName, new DeleteEntityArguments(playListId));
}
return builder.AddStep(
ActivityNames.DeletePlayListFromDb, DeletePlayListActivity.ExecuteEndpointName, new DeleteEntityArguments(playListId));
}
private void AddPictureRemovals(
RoutingSlipBuilder builder, PictureStepNames steps, PictureRoutes routes, long userId, EntityPictures? pictures)
{
if (pictures == null)
return;
private void AddPictureRemovals(
RoutingSlipBuilder builder, PictureStepNames steps, PictureRoutes routes, long userId, EntityPictures? pictures)
{
if (pictures == null)
return;
var bucket = storageConfiguration.Bucket;
var bucket = storageConfiguration.Bucket;
if (pictures.OriginalName is { } original)
builder.AddRemoveFile(steps.Original, bucket, routes.BuildOriginalPicturePath(userId, original));
if (pictures.SmallName is { } small)
builder.AddRemoveFile(steps.Small, bucket, routes.BuildPicturePath(PictureSize.Small, small));
if (pictures.MediumName is { } medium)
builder.AddRemoveFile(steps.Medium, bucket, routes.BuildPicturePath(PictureSize.Medium, medium));
if (pictures.LargeName is { } large)
builder.AddRemoveFile(steps.Large, bucket, routes.BuildPicturePath(PictureSize.Large, large));
if (pictures.OriginalName is { } original)
builder.AddRemoveFile(steps.Original, bucket, routes.BuildOriginalPicturePath(userId, original));
if (pictures.SmallName is { } small)
builder.AddRemoveFile(steps.Small, bucket, routes.BuildPicturePath(PictureSize.Small, small));
if (pictures.MediumName is { } medium)
builder.AddRemoveFile(steps.Medium, bucket, routes.BuildPicturePath(PictureSize.Medium, medium));
if (pictures.LargeName is { } large)
builder.AddRemoveFile(steps.Large, bucket, routes.BuildPicturePath(PictureSize.Large, large));
}
}
}
@@ -6,69 +6,70 @@ using Musify.Infrastructure.MassTransit.Activities.PlayLists;
using Musify.Infrastructure.MassTransit.Activities.UploadIntents;
using Musify.Infrastructure.MassTransit.Arguments;
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
/// <summary>
/// Moves an uploaded album/playlist picture to its final key, consumes the upload intent and hands over to the picture workflow.
/// Creation faults mark the whole entity as failed; update faults only report the picture as failed.
/// </summary>
public class PictureSourceRoutingSlipBuilder
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
{
public RoutingSlipBuilder Build(CreateAlbumResourcesEvent message, Guid? correlationId) =>
BuildSlip(
message.AlbumId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.AlbumCreation,
ActivityNames.PublishAlbumPictureProcessingEvent, PublishAlbumPictureProcessingEventActivity.ExecuteEndpointName,
new PublishAlbumPictureProcessingEventArguments(message.AlbumId, message.Bucket, message.PictureDestinationKey, message.Sizes));
public RoutingSlipBuilder Build(UpdateAlbumPictureSourceEvent message, Guid? correlationId) =>
BuildSlip(
message.AlbumId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.AlbumPicture,
ActivityNames.PublishAlbumPictureProcessingEvent, PublishAlbumPictureProcessingEventActivity.ExecuteEndpointName,
new PublishAlbumPictureProcessingEventArguments(message.AlbumId, message.Bucket, message.PictureDestinationKey, message.Sizes));
public RoutingSlipBuilder Build(CreatePlayListResourcesEvent message, Guid? correlationId) =>
BuildSlip(
message.PlayListId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.PlayListCreation,
ActivityNames.PublishPlayListPictureProcessingEvent, PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName,
new PublishPlayListPictureProcessingEventArguments(message.PlayListId, message.Bucket, message.PictureDestinationKey, message.Sizes));
public RoutingSlipBuilder Build(UpdatePlayListPictureSourceEvent message, Guid? correlationId) =>
BuildSlip(
message.PlayListId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.PlayListPicture,
ActivityNames.PublishPlayListPictureProcessingEvent, PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName,
new PublishPlayListPictureProcessingEventArguments(message.PlayListId, message.Bucket, message.PictureDestinationKey, message.Sizes));
private static RoutingSlipBuilder BuildSlip(
Guid subjectId,
Guid pictureIntentId,
string bucket,
string pictureSourceKey,
string pictureDestinationKey,
Guid? correlationId,
string processKind,
string publishStepName,
string publishEndpointName,
object publishArguments)
/// <summary>
/// Moves an uploaded album/playlist picture to its final key, consumes the upload intent and hands over to the picture workflow.
/// Creation faults mark the whole entity as failed; update faults only report the picture as failed.
/// </summary>
public class PictureSourceRoutingSlipBuilder
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.CopyPictureToFinal,
CopyFileInBucketActivity.ExecuteEndpointName,
new CopyFileInBucketArguments(bucket, pictureSourceKey, bucket, pictureDestinationKey))
.AddStep(
ActivityNames.ConsumeUploadIntents,
ConsumeUploadIntentsActivity.ExecuteEndpointName,
new ConsumeUploadIntentsArguments([pictureIntentId]))
.AddStep(publishStepName, publishEndpointName, publishArguments)
.TrackFaults(subjectId, processKind);
public RoutingSlipBuilder Build(CreateAlbumResourcesEvent message, Guid? correlationId) =>
BuildSlip(
message.AlbumId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.AlbumCreation,
ActivityNames.PublishAlbumPictureProcessingEvent, PublishAlbumPictureProcessingEventActivity.ExecuteEndpointName,
new PublishAlbumPictureProcessingEventArguments(message.AlbumId, message.Bucket, message.PictureDestinationKey, message.Sizes));
builder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, bucket);
builder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, pictureDestinationKey);
public RoutingSlipBuilder Build(UpdateAlbumPictureSourceEvent message, Guid? correlationId) =>
BuildSlip(
message.AlbumId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.AlbumPicture,
ActivityNames.PublishAlbumPictureProcessingEvent, PublishAlbumPictureProcessingEventActivity.ExecuteEndpointName,
new PublishAlbumPictureProcessingEventArguments(message.AlbumId, message.Bucket, message.PictureDestinationKey, message.Sizes));
return builder;
public RoutingSlipBuilder Build(CreatePlayListResourcesEvent message, Guid? correlationId) =>
BuildSlip(
message.PlayListId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.PlayListCreation,
ActivityNames.PublishPlayListPictureProcessingEvent, PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName,
new PublishPlayListPictureProcessingEventArguments(message.PlayListId, message.Bucket, message.PictureDestinationKey, message.Sizes));
public RoutingSlipBuilder Build(UpdatePlayListPictureSourceEvent message, Guid? correlationId) =>
BuildSlip(
message.PlayListId, message.PictureIntentId, message.Bucket, message.PictureSourceKey, message.PictureDestinationKey,
correlationId, RoutingSlipVariableNames.ProcessKinds.PlayListPicture,
ActivityNames.PublishPlayListPictureProcessingEvent, PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName,
new PublishPlayListPictureProcessingEventArguments(message.PlayListId, message.Bucket, message.PictureDestinationKey, message.Sizes));
private static RoutingSlipBuilder BuildSlip(
Guid subjectId,
Guid pictureIntentId,
string bucket,
string pictureSourceKey,
string pictureDestinationKey,
Guid? correlationId,
string processKind,
string publishStepName,
string publishEndpointName,
object publishArguments)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.CopyPictureToFinal,
CopyFileInBucketActivity.ExecuteEndpointName,
new CopyFileInBucketArguments(bucket, pictureSourceKey, bucket, pictureDestinationKey))
.AddStep(
ActivityNames.ConsumeUploadIntents,
ConsumeUploadIntentsActivity.ExecuteEndpointName,
new ConsumeUploadIntentsArguments([pictureIntentId]))
.AddStep(publishStepName, publishEndpointName, publishArguments)
.TrackFaults(subjectId, processKind);
builder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, bucket);
builder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, pictureDestinationKey);
return builder;
}
}
}
@@ -6,81 +6,82 @@ using Musify.Infrastructure.MassTransit.Activities.Files;
using Musify.Infrastructure.MassTransit.Activities.Pictures;
using Musify.Infrastructure.MassTransit.Arguments;
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
/// <summary>Downloads a picture, resizes it to the three sizes, uploads them and records the result on the owner.</summary>
public class PictureWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
{
public RoutingSlipBuilder Build(UpdateTrackPictureEvent message, Guid? correlationId) =>
BuildPictureWorkflow(
message.TrackId, message.Bucket, message.SourceKey, message.Sizes, correlationId,
ActivityNames.UpdateTrackPicture, UpdateTrackPictureActivity.ExecuteEndpointName,
RoutingSlipVariableNames.ProcessKinds.TrackPicture);
public RoutingSlipBuilder Build(UpdatePlayListPictureEvent message, Guid? correlationId) =>
BuildPictureWorkflow(
message.PlayListId, message.Bucket, message.SourceKey, message.Sizes, correlationId,
ActivityNames.UpdatePlayListPicture, UpdatePlayListPictureActivity.ExecuteEndpointName,
RoutingSlipVariableNames.ProcessKinds.PlayListPicture);
public RoutingSlipBuilder Build(UpdateAlbumPictureEvent message, Guid? correlationId) =>
BuildPictureWorkflow(
message.AlbumId, message.Bucket, message.SourceKey, message.Sizes, correlationId,
ActivityNames.UpdateAlbumPicture, UpdateAlbumPictureActivity.ExecuteEndpointName,
RoutingSlipVariableNames.ProcessKinds.AlbumPicture);
private RoutingSlipBuilder BuildPictureWorkflow(
Guid subjectId,
string bucket,
string sourceKey,
ImageSizes sizes,
Guid? correlationId,
string updateStepName,
string updateEndpointName,
string processKind)
/// <summary>Downloads a picture, resizes it to the three sizes, uploads them and records the result on the owner.</summary>
public class PictureWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.GeneratePictureWorkflowPaths,
GeneratePictureWorkflowPathsActivity.ExecuteEndpointName,
new GeneratePictureWorkflowPathsArguments(workerConfiguration.Routes.TemporaryFilesDirectory, sourceKey))
.AddStep(
ActivityNames.DownloadFile,
DownloadFileFromBucketActivity.ExecuteEndpointName,
new DownloadFileFromBucketArguments(bucket, sourceKey, RoutingSlipVariableNames.Picture.OriginalFilePath));
public RoutingSlipBuilder Build(UpdateTrackPictureEvent message, Guid? correlationId) =>
BuildPictureWorkflow(
message.TrackId, message.Bucket, message.SourceKey, message.Sizes, correlationId,
ActivityNames.UpdateTrackPicture, UpdateTrackPictureActivity.ExecuteEndpointName,
RoutingSlipVariableNames.ProcessKinds.TrackPicture);
AddResize(builder, ActivityNames.ResizeSmall, ActivityNames.UploadSmall, bucket, RoutingSlipVariableNames.Picture.SmallResizedFilePath, sizes.Small);
AddResize(builder, ActivityNames.ResizeMedium, ActivityNames.UploadMedium, bucket, RoutingSlipVariableNames.Picture.MediumResizedFilePath, sizes.Medium);
AddResize(builder, ActivityNames.ResizeLarge, ActivityNames.UploadLarge, bucket, RoutingSlipVariableNames.Picture.LargeResizedFilePath, sizes.Large);
public RoutingSlipBuilder Build(UpdatePlayListPictureEvent message, Guid? correlationId) =>
BuildPictureWorkflow(
message.PlayListId, message.Bucket, message.SourceKey, message.Sizes, correlationId,
ActivityNames.UpdatePlayListPicture, UpdatePlayListPictureActivity.ExecuteEndpointName,
RoutingSlipVariableNames.ProcessKinds.PlayListPicture);
return builder
.AddStep(
updateStepName,
updateEndpointName,
new UpdatePicturesArguments(
subjectId,
sourceKey,
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
RoutingSlipVariableNames.Picture.LargeResizedFilePath))
.TrackFaults(subjectId, processKind);
public RoutingSlipBuilder Build(UpdateAlbumPictureEvent message, Guid? correlationId) =>
BuildPictureWorkflow(
message.AlbumId, message.Bucket, message.SourceKey, message.Sizes, correlationId,
ActivityNames.UpdateAlbumPicture, UpdateAlbumPictureActivity.ExecuteEndpointName,
RoutingSlipVariableNames.ProcessKinds.AlbumPicture);
private RoutingSlipBuilder BuildPictureWorkflow(
Guid subjectId,
string bucket,
string sourceKey,
ImageSizes sizes,
Guid? correlationId,
string updateStepName,
string updateEndpointName,
string processKind)
{
var builder = RoutingSlips.Create(correlationId)
.AddStep(
ActivityNames.GeneratePictureWorkflowPaths,
GeneratePictureWorkflowPathsActivity.ExecuteEndpointName,
new GeneratePictureWorkflowPathsArguments(workerConfiguration.Routes.TemporaryFilesDirectory, sourceKey))
.AddStep(
ActivityNames.DownloadFile,
DownloadFileFromBucketActivity.ExecuteEndpointName,
new DownloadFileFromBucketArguments(bucket, sourceKey, RoutingSlipVariableNames.Picture.OriginalFilePath));
AddResize(builder, ActivityNames.ResizeSmall, ActivityNames.UploadSmall, bucket, RoutingSlipVariableNames.Picture.SmallResizedFilePath, sizes.Small);
AddResize(builder, ActivityNames.ResizeMedium, ActivityNames.UploadMedium, bucket, RoutingSlipVariableNames.Picture.MediumResizedFilePath, sizes.Medium);
AddResize(builder, ActivityNames.ResizeLarge, ActivityNames.UploadLarge, bucket, RoutingSlipVariableNames.Picture.LargeResizedFilePath, sizes.Large);
return builder
.AddStep(
updateStepName,
updateEndpointName,
new UpdatePicturesArguments(
subjectId,
sourceKey,
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
RoutingSlipVariableNames.Picture.LargeResizedFilePath))
.TrackFaults(subjectId, processKind);
}
private static void AddResize(
RoutingSlipBuilder builder,
string resizeStepName,
string uploadStepName,
string bucket,
string resizedFileVariable,
ImageSize size) =>
builder
.AddStep(
resizeStepName,
ResizePictureActivity.ExecuteEndpointName,
new ResizePictureLocalArguments(
RoutingSlipVariableNames.Picture.OriginalFilePath, resizedFileVariable, size.Width, size.Height))
.AddStep(
uploadStepName,
UploadFileToBucketActivity.ExecuteEndpointName,
new UploadFileToBucketArguments(resizedFileVariable, bucket, size.SavePath));
}
private static void AddResize(
RoutingSlipBuilder builder,
string resizeStepName,
string uploadStepName,
string bucket,
string resizedFileVariable,
ImageSize size) =>
builder
.AddStep(
resizeStepName,
ResizePictureActivity.ExecuteEndpointName,
new ResizePictureLocalArguments(
RoutingSlipVariableNames.Picture.OriginalFilePath, resizedFileVariable, size.Width, size.Height))
.AddStep(
uploadStepName,
UploadFileToBucketActivity.ExecuteEndpointName,
new UploadFileToBucketArguments(resizedFileVariable, bucket, size.SavePath));
}