Add editorconfig and analyzers, format backend code
This commit is contained in:
+17
-18
@@ -5,28 +5,27 @@ using Musify.Application.Contracts;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Albums
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Albums;
|
||||
|
||||
internal class MarkAlbumAsFailedActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkAlbumAsFailedActivity> logger)
|
||||
: IExecuteActivity<MarkAlbumAsFailedArguments>
|
||||
{
|
||||
internal class MarkAlbumAsFailedActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkAlbumAsFailedActivity> logger)
|
||||
: IExecuteActivity<MarkAlbumAsFailedArguments>
|
||||
public const string ExecuteEndpointName = "mark-album-as-failed";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkAlbumAsFailedArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "mark-album-as-failed";
|
||||
var album = await database.Albums
|
||||
.SingleOrDefaultAsync(a => a.Id == executeContext.Arguments.AlbumId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkAlbumAsFailedArguments> executeContext)
|
||||
if (album != null)
|
||||
{
|
||||
var album = await database.Albums
|
||||
.SingleOrDefaultAsync(a => a.Id == executeContext.Arguments.AlbumId, executeContext.CancellationToken);
|
||||
|
||||
if (album != null)
|
||||
{
|
||||
album.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
logger.LogInformation("Marked album {AlbumId} as failed", executeContext.Arguments.AlbumId);
|
||||
}
|
||||
|
||||
return executeContext.Completed();
|
||||
album.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
logger.LogInformation("Marked album {AlbumId} as failed", executeContext.Arguments.AlbumId);
|
||||
}
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+21
-22
@@ -3,32 +3,31 @@ using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Albums
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Albums;
|
||||
|
||||
internal class PublishAlbumPictureProcessingEventActivity(
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<PublishAlbumPictureProcessingEventActivity> logger)
|
||||
: IExecuteActivity<PublishAlbumPictureProcessingEventArguments>
|
||||
{
|
||||
internal class PublishAlbumPictureProcessingEventActivity(
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<PublishAlbumPictureProcessingEventActivity> logger)
|
||||
: IExecuteActivity<PublishAlbumPictureProcessingEventArguments>
|
||||
public const string ExecuteEndpointName = "publish-album-picture-processing-event";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<PublishAlbumPictureProcessingEventArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "publish-album-picture-processing-event";
|
||||
var arguments = executeContext.Arguments;
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<PublishAlbumPictureProcessingEventArguments> executeContext)
|
||||
{
|
||||
var arguments = executeContext.Arguments;
|
||||
await publishEndpoint.Publish(
|
||||
new UpdateAlbumPictureEvent(
|
||||
arguments.AlbumId,
|
||||
arguments.Bucket,
|
||||
arguments.FinalPictureKey,
|
||||
arguments.Small,
|
||||
arguments.Medium,
|
||||
arguments.Large),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new UpdateAlbumPictureEvent(
|
||||
arguments.AlbumId,
|
||||
arguments.Bucket,
|
||||
arguments.FinalPictureKey,
|
||||
arguments.Small,
|
||||
arguments.Medium,
|
||||
arguments.Large),
|
||||
executeContext.CancellationToken);
|
||||
logger.LogInformation("Published picture processing event for album {AlbumId}", arguments.AlbumId);
|
||||
|
||||
logger.LogInformation("Published picture processing event for album {AlbumId}", arguments.AlbumId);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+51
-52
@@ -6,68 +6,67 @@ using Musify.Domain.Entities;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Audio
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Audio;
|
||||
|
||||
internal class GenerateAudioWorkflowPathsActivity(
|
||||
IDatabase database,
|
||||
ILogger<GenerateAudioWorkflowPathsActivity> logger)
|
||||
: IExecuteActivity<GenerateAudioWorkflowPathsArguments>
|
||||
{
|
||||
internal class GenerateAudioWorkflowPathsActivity(
|
||||
IDatabase database,
|
||||
ILogger<GenerateAudioWorkflowPathsActivity> logger)
|
||||
: IExecuteActivity<GenerateAudioWorkflowPathsArguments>
|
||||
public const string ExecuteEndpointName = "generate-audio-workflow-paths";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<GenerateAudioWorkflowPathsArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "generate-audio-workflow-paths";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<GenerateAudioWorkflowPathsArguments> executeContext)
|
||||
Track track;
|
||||
try
|
||||
{
|
||||
Track track;
|
||||
try
|
||||
var getTrack = await database.Tracks.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
track = getTrack ?? throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found.");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to retrieve track for TrackId {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Processing;
|
||||
var folderName = Guid.NewGuid().ToString();
|
||||
var sourceFileName = Path.GetFileName(executeContext.Arguments.SourceKey);
|
||||
var workingDirectory = Path.Combine(executeContext.Arguments.TemporaryRootDirectory, folderName);
|
||||
var sourceFilePath = Path.Combine(workingDirectory, sourceFileName);
|
||||
|
||||
Directory.CreateDirectory(workingDirectory);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogDebug("Generated audio workflow paths in {WorkingDirectory}", workingDirectory);
|
||||
|
||||
return executeContext.CompletedWithVariables(new Dictionary<string, object>
|
||||
{
|
||||
var getTrack = await database.Tracks.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
track = getTrack ?? throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found.");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to retrieve track for TrackId {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
[RoutingSlipVariableNames.Workflow.TemporalDirectory] = workingDirectory,
|
||||
[RoutingSlipVariableNames.Audio.SourceFilePath] = sourceFilePath,
|
||||
[RoutingSlipVariableNames.Audio.TranscodedDirectory] = workingDirectory
|
||||
});
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to generate audio workflow paths for {SourceKey}",
|
||||
executeContext.Arguments.SourceKey);
|
||||
|
||||
try
|
||||
{
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Processing;
|
||||
var folderName = Guid.NewGuid().ToString();
|
||||
var sourceFileName = Path.GetFileName(executeContext.Arguments.SourceKey);
|
||||
var workingDirectory = Path.Combine(executeContext.Arguments.TemporaryRootDirectory, folderName);
|
||||
var sourceFilePath = Path.Combine(workingDirectory, sourceFileName);
|
||||
|
||||
Directory.CreateDirectory(workingDirectory);
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogDebug("Generated audio workflow paths in {WorkingDirectory}", workingDirectory);
|
||||
|
||||
return executeContext.CompletedWithVariables(new Dictionary<string, object>
|
||||
{
|
||||
[RoutingSlipVariableNames.Workflow.TemporalDirectory] = workingDirectory,
|
||||
[RoutingSlipVariableNames.Audio.SourceFilePath] = sourceFilePath,
|
||||
[RoutingSlipVariableNames.Audio.TranscodedDirectory] = workingDirectory
|
||||
} );
|
||||
}
|
||||
catch (Exception exception)
|
||||
catch (Exception dbException)
|
||||
{
|
||||
logger.LogError(exception, "Failed to generate audio workflow paths for {SourceKey}",
|
||||
executeContext.Arguments.SourceKey);
|
||||
|
||||
try
|
||||
{
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
}
|
||||
catch (Exception dbException)
|
||||
{
|
||||
logger.LogError(dbException, "Failed to update ProcessingStatus to Failed for track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
throw;
|
||||
logger.LogError(dbException, "Failed to update ProcessingStatus to Failed for track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+78
-74
@@ -7,92 +7,96 @@ using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Audio
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Audio;
|
||||
|
||||
internal class TranscodeAudioActivity(
|
||||
IDatabase database,
|
||||
IAudioTranscoderService audioTranscoder,
|
||||
ILogger<TranscodeAudioActivity> logger)
|
||||
: IActivity<TranscodeAudioArguments, TranscodeAudioLog>
|
||||
{
|
||||
internal class TranscodeAudioActivity(
|
||||
IDatabase database,
|
||||
IAudioTranscoderService audioTranscoder,
|
||||
ILogger<TranscodeAudioActivity> logger)
|
||||
: IActivity<TranscodeAudioArguments, TranscodeAudioLog>
|
||||
public const string ExecuteEndpointName = "transcode-audio";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<TranscodeAudioArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "transcode-audio";
|
||||
var sourceFilePath = executeContext.GetVariable<string>(executeContext.Arguments.SourceFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(sourceFilePath, nameof(sourceFilePath));
|
||||
var workingDirectory = executeContext.GetVariable<string>(executeContext.Arguments.WorkingDirectoryVariable);
|
||||
ArgumentNullException.ThrowIfNull(workingDirectory, nameof(workingDirectory));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<TranscodeAudioArguments> executeContext)
|
||||
Track track;
|
||||
try
|
||||
{
|
||||
var sourceFilePath = executeContext.GetVariable<string>(executeContext.Arguments.SourceFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(sourceFilePath, nameof(sourceFilePath));
|
||||
var workingDirectory = executeContext.GetVariable<string>(executeContext.Arguments.WorkingDirectoryVariable);
|
||||
ArgumentNullException.ThrowIfNull(workingDirectory, nameof(workingDirectory));
|
||||
|
||||
Track track;
|
||||
try
|
||||
{
|
||||
var getTrack = await database.Tracks.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
track = getTrack ?? throw new InvalidOperationException($"Track with Id {executeContext.Arguments.TrackId} not found");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to retrieve track with Id {TrackId} from database", executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
AudioTranscodeResult transcodeResult;
|
||||
await using (var fileStream = File.OpenRead(sourceFilePath))
|
||||
{
|
||||
transcodeResult = await audioTranscoder.TranscodeToAudioFileAsync(
|
||||
fileStream,
|
||||
workingDirectory,
|
||||
executeContext.CancellationToken);
|
||||
}
|
||||
|
||||
if (transcodeResult.StatusCode != 0)
|
||||
throw new InvalidOperationException($"ffmpeg transcoding failed with exit code {transcodeResult.StatusCode}.");
|
||||
|
||||
File.Delete(sourceFilePath);
|
||||
|
||||
var log = new TranscodeAudioLog(workingDirectory);
|
||||
return executeContext.CompletedWithVariables(log, new Dictionary<string, object>
|
||||
{
|
||||
[RoutingSlipVariableNames.Audio.DurationSeconds] = (int)Math.Round(transcodeResult.Duration.TotalSeconds)
|
||||
} );
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to transcode {SourceFilePath}", sourceFilePath);
|
||||
|
||||
try
|
||||
{
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
}
|
||||
catch (Exception dbException)
|
||||
{
|
||||
logger.LogError(dbException, "Failed to update ProcessingStatus to Failed for track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
var getTrack = await database.Tracks.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
track = getTrack ?? throw new InvalidOperationException($"Track with Id {executeContext.Arguments.TrackId} not found");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to retrieve track with Id {TrackId} from database", executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<TranscodeAudioLog> compensateContext)
|
||||
try
|
||||
{
|
||||
AudioTranscodeResult transcodeResult;
|
||||
await using (var fileStream = File.OpenRead(sourceFilePath))
|
||||
{
|
||||
transcodeResult = await audioTranscoder.TranscodeToAudioFileAsync(
|
||||
fileStream,
|
||||
workingDirectory,
|
||||
executeContext.CancellationToken);
|
||||
}
|
||||
|
||||
if (transcodeResult.StatusCode != 0)
|
||||
throw new InvalidOperationException($"ffmpeg transcoding failed with exit code {transcodeResult.StatusCode}.");
|
||||
|
||||
File.Delete(sourceFilePath);
|
||||
|
||||
var log = new TranscodeAudioLog(workingDirectory);
|
||||
return executeContext.CompletedWithVariables(log, new Dictionary<string, object>
|
||||
{
|
||||
[RoutingSlipVariableNames.Audio.DurationSeconds] = (int)Math.Round(transcodeResult.Duration.TotalSeconds)
|
||||
});
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to transcode {SourceFilePath}", sourceFilePath);
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(compensateContext.Log.WorkingDirectory))
|
||||
Directory.Delete(compensateContext.Log.WorkingDirectory, recursive: true);
|
||||
else
|
||||
logger.LogWarning("Working directory {WorkingDirectory} not found during compensation",
|
||||
compensateContext.Log.WorkingDirectory);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
}
|
||||
catch (Exception exception)
|
||||
catch (Exception dbException)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate transcoded audio directory {WorkingDirectory}", compensateContext.Log.WorkingDirectory);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
logger.LogError(dbException, "Failed to update ProcessingStatus to Failed for track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<TranscodeAudioLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(compensateContext.Log.WorkingDirectory))
|
||||
{
|
||||
Directory.Delete(compensateContext.Log.WorkingDirectory, recursive: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogWarning("Working directory {WorkingDirectory} not found during compensation",
|
||||
compensateContext.Log.WorkingDirectory);
|
||||
}
|
||||
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate transcoded audio directory {WorkingDirectory}", compensateContext.Log.WorkingDirectory);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+91
-92
@@ -8,109 +8,108 @@ using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Audio
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Audio;
|
||||
|
||||
internal class UpdateTrackAudioActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdateTrackAudioActivity> logger)
|
||||
: IActivity<UpdateTrackAudioArguments, UpdateTrackAudioLog>
|
||||
{
|
||||
internal class UpdateTrackAudioActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdateTrackAudioActivity> logger)
|
||||
: IActivity<UpdateTrackAudioArguments, UpdateTrackAudioLog>
|
||||
public const string ExecuteEndpointName = "update-track-audio";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdateTrackAudioArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "update-track-audio";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdateTrackAudioArguments> executeContext)
|
||||
Track track;
|
||||
try
|
||||
{
|
||||
Track track;
|
||||
try
|
||||
{
|
||||
var getTrack = await database.Tracks.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
track = getTrack ?? throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to retrieve track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
|
||||
var audioFolderKey = executeContext.Arguments.AudioFolderKey;
|
||||
logger.LogDebug("Resolved audio folder key: {AudioFolderKey}", audioFolderKey);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(audioFolderKey))
|
||||
{
|
||||
logger.LogWarning("Audio folder key is empty for track {TrackId}; skipping update", track.Id);
|
||||
await publishEndpoint.Publish(
|
||||
new TrackAudioProcessed(executeContext.Arguments.TrackId),
|
||||
executeContext.CancellationToken);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var durationSeconds = executeContext.GetVariable<double>(executeContext.Arguments.DurationSecondsVariable)
|
||||
?? throw new InvalidOperationException($"Missing routing slip variable {executeContext.Arguments.DurationSecondsVariable}");
|
||||
|
||||
var log = new UpdateTrackAudioLog(
|
||||
track.Id,
|
||||
track.Audio.FolderName,
|
||||
track.DurationSeconds);
|
||||
|
||||
track.Audio.FolderName = Path.GetFileName(audioFolderKey);
|
||||
track.DurationSeconds = durationSeconds;
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Completed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated track {TrackId} audio", executeContext.Arguments.TrackId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new TrackAudioProcessed(executeContext.Arguments.TrackId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed(log);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to update track {TrackId} audio",
|
||||
executeContext.Arguments.TrackId);
|
||||
|
||||
try
|
||||
{
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
}
|
||||
catch (Exception dbException)
|
||||
{
|
||||
logger.LogError(dbException, "Failed to update ProcessingStatus to Failed for track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
var getTrack = await database.Tracks.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
track = getTrack ?? throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found");
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to retrieve track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdateTrackAudioLog> compensateContext)
|
||||
var audioFolderKey = executeContext.Arguments.AudioFolderKey;
|
||||
logger.LogDebug("Resolved audio folder key: {AudioFolderKey}", audioFolderKey);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(audioFolderKey))
|
||||
{
|
||||
logger.LogWarning("Audio folder key is empty for track {TrackId}; skipping update", track.Id);
|
||||
await publishEndpoint.Publish(
|
||||
new TrackAudioProcessed(executeContext.Arguments.TrackId),
|
||||
executeContext.CancellationToken);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var durationSeconds = executeContext.GetVariable<double>(executeContext.Arguments.DurationSecondsVariable)
|
||||
?? throw new InvalidOperationException($"Missing routing slip variable {executeContext.Arguments.DurationSecondsVariable}");
|
||||
|
||||
var log = new UpdateTrackAudioLog(
|
||||
track.Id,
|
||||
track.Audio.FolderName,
|
||||
track.DurationSeconds);
|
||||
|
||||
track.Audio.FolderName = Path.GetFileName(audioFolderKey);
|
||||
track.DurationSeconds = durationSeconds;
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Completed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated track {TrackId} audio", executeContext.Arguments.TrackId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new TrackAudioProcessed(executeContext.Arguments.TrackId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed(log);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to update track {TrackId} audio",
|
||||
executeContext.Arguments.TrackId);
|
||||
|
||||
try
|
||||
{
|
||||
var track = await database.Tracks.SingleOrDefaultAsync(t => t.Id == compensateContext.Log.TrackId, compensateContext.CancellationToken);
|
||||
if (track == null)
|
||||
throw new InvalidOperationException($"Track with id {compensateContext.Log.TrackId} not found");
|
||||
|
||||
track.Audio.FolderName = compensateContext.Log.PreviousAudioFolderName;
|
||||
track.DurationSeconds = compensateContext.Log.PreviousDurationSeconds;
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Compensated track {TrackId} audio", compensateContext.Log.TrackId);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
}
|
||||
catch (Exception exception)
|
||||
catch (Exception dbException)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate track {TrackId} audio",
|
||||
compensateContext.Log.TrackId);
|
||||
return compensateContext.Failed(exception);
|
||||
logger.LogError(dbException, "Failed to update ProcessingStatus to Failed for track {TrackId}",
|
||||
executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdateTrackAudioLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
var track = await database.Tracks.SingleOrDefaultAsync(t => t.Id == compensateContext.Log.TrackId, compensateContext.CancellationToken);
|
||||
if (track == null)
|
||||
throw new InvalidOperationException($"Track with id {compensateContext.Log.TrackId} not found");
|
||||
|
||||
track.Audio.FolderName = compensateContext.Log.PreviousAudioFolderName;
|
||||
track.DurationSeconds = compensateContext.Log.PreviousDurationSeconds;
|
||||
track.Audio.TranscodeStatus = ProcessingStatus.Failed;
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Compensated track {TrackId} audio", compensateContext.Log.TrackId);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate track {TrackId} audio",
|
||||
compensateContext.Log.TrackId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-46
@@ -4,58 +4,57 @@ using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
|
||||
internal class CopyFileInBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<CopyFileInBucketActivity> logger)
|
||||
: IActivity<CopyFileInBucketArguments, CopyFileInBucketLog>
|
||||
{
|
||||
internal class CopyFileInBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<CopyFileInBucketActivity> logger)
|
||||
: IActivity<CopyFileInBucketArguments, CopyFileInBucketLog>
|
||||
public const string ExecuteEndpointName = "copy-file-in-bucket";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<CopyFileInBucketArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "copy-file-in-bucket";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<CopyFileInBucketArguments> executeContext)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
await storageHandler.CopyFileAsync(
|
||||
executeContext.Arguments.SourceBucket,
|
||||
executeContext.Arguments.SourceKey,
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
executeContext.Arguments.DestinationKey,
|
||||
executeContext.CancellationToken);
|
||||
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;
|
||||
}
|
||||
return executeContext.Completed(new CopyFileInBucketLog(
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
executeContext.Arguments.DestinationKey));
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<CopyFileInBucketLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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<CompensationResult> Compensate(CompensateContext<CopyFileInBucketLog> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-46
@@ -4,60 +4,59 @@ using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
|
||||
internal class DownloadFileFromBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<DownloadFileFromBucketActivity> logger)
|
||||
: IActivity<DownloadFileFromBucketArguments, DownloadFileFromBucketLog>
|
||||
{
|
||||
internal class DownloadFileFromBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<DownloadFileFromBucketActivity> logger)
|
||||
: IActivity<DownloadFileFromBucketArguments, DownloadFileFromBucketLog>
|
||||
public const string ExecuteEndpointName = "download-file-from-bucket";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DownloadFileFromBucketArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "download-file-from-bucket";
|
||||
var destinationPath = executeContext.GetVariable<string>(executeContext.Arguments.DestinationFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(destinationPath, nameof(destinationPath));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DownloadFileFromBucketArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var destinationPath = executeContext.GetVariable<string>(executeContext.Arguments.DestinationFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(destinationPath, nameof(destinationPath));
|
||||
using var fileStream = await storageHandler.GetFileAsync(
|
||||
executeContext.Arguments.Bucket,
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.CancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
using var fileStream = await storageHandler.GetFileAsync(
|
||||
executeContext.Arguments.Bucket,
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.CancellationToken);
|
||||
var destinationDirectory = Path.GetDirectoryName(destinationPath);
|
||||
if (!string.IsNullOrWhiteSpace(destinationDirectory))
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
|
||||
var destinationDirectory = Path.GetDirectoryName(destinationPath);
|
||||
if (!string.IsNullOrWhiteSpace(destinationDirectory))
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
if (fileStream.CanSeek)
|
||||
fileStream.Position = 0;
|
||||
|
||||
if (fileStream.CanSeek)
|
||||
fileStream.Position = 0;
|
||||
|
||||
using var destinationStream = File.Create(destinationPath);
|
||||
await fileStream.CopyToAsync(destinationStream, executeContext.CancellationToken);
|
||||
return executeContext.Completed(new DownloadFileFromBucketLog(
|
||||
executeContext.Arguments.Bucket,
|
||||
executeContext.Arguments.Key,
|
||||
destinationPath));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to download file from bucket");
|
||||
throw;
|
||||
}
|
||||
using var destinationStream = File.Create(destinationPath);
|
||||
await fileStream.CopyToAsync(destinationStream, executeContext.CancellationToken);
|
||||
return executeContext.Completed(new DownloadFileFromBucketLog(
|
||||
executeContext.Arguments.Bucket,
|
||||
executeContext.Arguments.Key,
|
||||
destinationPath));
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<DownloadFileFromBucketLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate downloaded file {DestinationFilePath}", compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
logger.LogError(exception, "Failed to download file from bucket");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<DownloadFileFromBucketLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate downloaded file {DestinationFilePath}", compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+51
-52
@@ -3,67 +3,66 @@ using Microsoft.Extensions.Logging;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
|
||||
internal class DownloadFileFromUrlActivity(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<DownloadFileFromUrlActivity> logger)
|
||||
: IActivity<DownloadFileFromUrlArguments, DownloadFileFromUrlLog>
|
||||
{
|
||||
internal class DownloadFileFromUrlActivity(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<DownloadFileFromUrlActivity> logger)
|
||||
: IActivity<DownloadFileFromUrlArguments, DownloadFileFromUrlLog>
|
||||
public const string ExecuteEndpointName = "download-file-from-url";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DownloadFileFromUrlArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "download-file-from-url";
|
||||
var destinationPath = executeContext.GetVariable<string>(executeContext.Arguments.DestinationFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(destinationPath, nameof(destinationPath));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DownloadFileFromUrlArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var destinationPath = executeContext.GetVariable<string>(executeContext.Arguments.DestinationFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(destinationPath, nameof(destinationPath));
|
||||
var httpClient = httpClientFactory.CreateClient();
|
||||
|
||||
try
|
||||
using var response = await httpClient.GetAsync(
|
||||
executeContext.Arguments.SourceUrl,
|
||||
HttpCompletionOption.ResponseHeadersRead,
|
||||
executeContext.CancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var destinationDirectory = Path.GetDirectoryName(destinationPath);
|
||||
if (!string.IsNullOrWhiteSpace(destinationDirectory))
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
|
||||
await using (var destinationStream = File.Create(destinationPath))
|
||||
{
|
||||
var httpClient = httpClientFactory.CreateClient();
|
||||
|
||||
using var response = await httpClient.GetAsync(
|
||||
executeContext.Arguments.SourceUrl,
|
||||
HttpCompletionOption.ResponseHeadersRead,
|
||||
executeContext.CancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var destinationDirectory = Path.GetDirectoryName(destinationPath);
|
||||
if (!string.IsNullOrWhiteSpace(destinationDirectory))
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
|
||||
await using (var destinationStream = File.Create(destinationPath))
|
||||
{
|
||||
await response.Content.CopyToAsync(destinationStream, executeContext.CancellationToken);
|
||||
}
|
||||
|
||||
logger.LogInformation("Downloaded {SourceUrl} to {DestinationPath}",
|
||||
executeContext.Arguments.SourceUrl, destinationPath);
|
||||
|
||||
return executeContext.Completed(new DownloadFileFromUrlLog(
|
||||
executeContext.Arguments.SourceUrl,
|
||||
destinationPath));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to download file from {SourceUrl}", executeContext.Arguments.SourceUrl);
|
||||
throw;
|
||||
await response.Content.CopyToAsync(destinationStream, executeContext.CancellationToken);
|
||||
}
|
||||
|
||||
logger.LogInformation("Downloaded {SourceUrl} to {DestinationPath}",
|
||||
executeContext.Arguments.SourceUrl, destinationPath);
|
||||
|
||||
return executeContext.Completed(new DownloadFileFromUrlLog(
|
||||
executeContext.Arguments.SourceUrl,
|
||||
destinationPath));
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<DownloadFileFromUrlLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(compensateContext.Log.DestinationFilePath))
|
||||
File.Delete(compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate downloaded file {DestinationFilePath}",
|
||||
compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
logger.LogError(exception, "Failed to download file from {SourceUrl}", executeContext.Arguments.SourceUrl);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<DownloadFileFromUrlLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(compensateContext.Log.DestinationFilePath))
|
||||
File.Delete(compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate downloaded file {DestinationFilePath}",
|
||||
compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-38
@@ -1,46 +1,45 @@
|
||||
using MassTransit;
|
||||
using Amazon.S3;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using System.Net;
|
||||
using Amazon.S3;
|
||||
using MassTransit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
|
||||
internal class RemoveFileFromBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<RemoveFileFromBucketActivity> logger)
|
||||
: IExecuteActivity<RemoveFileFromBucketArguments>
|
||||
{
|
||||
internal class RemoveFileFromBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<RemoveFileFromBucketActivity> logger)
|
||||
: IExecuteActivity<RemoveFileFromBucketArguments>
|
||||
{
|
||||
public const string ExecuteEndpointName = "remove-file-from-bucket";
|
||||
public const string ExecuteEndpointName = "remove-file-from-bucket";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<RemoveFileFromBucketArguments> executeContext)
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<RemoveFileFromBucketArguments> executeContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
await storageHandler.RemoveFileAsync(
|
||||
executeContext.Arguments.Bucket,
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.CancellationToken);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
catch (AmazonS3Exception exception) when (
|
||||
exception.StatusCode == HttpStatusCode.NotFound
|
||||
|| string.Equals(exception.ErrorCode, "NoSuchKey", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogInformation(
|
||||
"Key {Key} not found in bucket {Bucket}, skipping",
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.Arguments.Bucket);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to remove {Key} from bucket {Bucket}",
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.Arguments.Bucket);
|
||||
throw;
|
||||
}
|
||||
await storageHandler.RemoveFileAsync(
|
||||
executeContext.Arguments.Bucket,
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.CancellationToken);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
catch (AmazonS3Exception exception) when (
|
||||
exception.StatusCode == HttpStatusCode.NotFound
|
||||
|| string.Equals(exception.ErrorCode, "NoSuchKey", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogInformation(
|
||||
"Key {Key} not found in bucket {Bucket}, skipping",
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.Arguments.Bucket);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to remove {Key} from bucket {Bucket}",
|
||||
executeContext.Arguments.Key,
|
||||
executeContext.Arguments.Bucket);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
-46
@@ -4,62 +4,61 @@ using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
|
||||
internal class TransferFilesToBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<TransferFilesToBucketActivity> logger)
|
||||
: IActivity<TransferFilesToBucketArguments, TransferFilesToBucketLog>
|
||||
{
|
||||
internal class TransferFilesToBucketActivity(
|
||||
IStorageService storageHandler,
|
||||
ILogger<TransferFilesToBucketActivity> logger)
|
||||
: IActivity<TransferFilesToBucketArguments, TransferFilesToBucketLog>
|
||||
public const string ExecuteEndpointName = "transfer-files-to-bucket";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<TransferFilesToBucketArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "transfer-files-to-bucket";
|
||||
var folderPath = executeContext.GetVariable<string>(executeContext.Arguments.SourceDirectoryVariable);
|
||||
ArgumentNullException.ThrowIfNull(folderPath, nameof(folderPath));
|
||||
var destinationKey = executeContext.Arguments.DestinationKey;
|
||||
ArgumentNullException.ThrowIfNull(destinationKey, nameof(destinationKey));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<TransferFilesToBucketArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var folderPath = executeContext.GetVariable<string>(executeContext.Arguments.SourceDirectoryVariable);
|
||||
ArgumentNullException.ThrowIfNull(folderPath, nameof(folderPath));
|
||||
var destinationKey = executeContext.Arguments.DestinationKey;
|
||||
ArgumentNullException.ThrowIfNull(destinationKey, nameof(destinationKey));
|
||||
var uploadedKeys = await storageHandler.TransferFilesAsync(
|
||||
folderPath,
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
destinationKey,
|
||||
executeContext.CancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
var uploadedKeys = await storageHandler.TransferFilesAsync(
|
||||
folderPath,
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
destinationKey,
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed(new TransferFilesToBucketLog(
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
uploadedKeys.ToArray()));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to transfer files from {FolderPath} to {DestinationBucket}",
|
||||
folderPath,
|
||||
executeContext.Arguments.DestinationBucket);
|
||||
throw;
|
||||
}
|
||||
return executeContext.Completed(new TransferFilesToBucketLog(
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
uploadedKeys.ToArray()));
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<TransferFilesToBucketLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var uploadedKey in compensateContext.Log.UploadedKeys)
|
||||
{
|
||||
await storageHandler.RemoveFileAsync(
|
||||
compensateContext.Log.DestinationBucket,
|
||||
uploadedKey,
|
||||
compensateContext.CancellationToken);
|
||||
}
|
||||
logger.LogError(exception, "Failed to transfer files from {FolderPath} to {DestinationBucket}",
|
||||
folderPath,
|
||||
executeContext.Arguments.DestinationBucket);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<TransferFilesToBucketLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var uploadedKey in compensateContext.Log.UploadedKeys)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate file transfers to {DestinationBucket}", compensateContext.Log.DestinationBucket);
|
||||
return compensateContext.Failed(exception);
|
||||
await storageHandler.RemoveFileAsync(
|
||||
compensateContext.Log.DestinationBucket,
|
||||
uploadedKey,
|
||||
compensateContext.CancellationToken);
|
||||
}
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate file transfers to {DestinationBucket}", compensateContext.Log.DestinationBucket);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+46
-47
@@ -4,58 +4,57 @@ using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
|
||||
internal class UploadFileToBucketActivity(IStorageService storageHandler,
|
||||
ILogger<UploadFileToBucketActivity> logger)
|
||||
: IActivity<UploadFileToBucketArguments, UploadFileToBucketLog>
|
||||
{
|
||||
internal class UploadFileToBucketActivity(IStorageService storageHandler,
|
||||
ILogger<UploadFileToBucketActivity> logger)
|
||||
: IActivity<UploadFileToBucketArguments, UploadFileToBucketLog>
|
||||
public const string ExecuteEndpointName = "upload-file-to-bucket";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UploadFileToBucketArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "upload-file-to-bucket";
|
||||
var sourceFilePath = executeContext.GetVariable<string>(executeContext.Arguments.FilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(sourceFilePath, nameof(sourceFilePath));
|
||||
var fileName = Path.GetFileName(sourceFilePath);
|
||||
var destinationKey = string.Join('/', new[] { executeContext.Arguments.DestinationRoute, fileName }
|
||||
.Where(static s => !string.IsNullOrWhiteSpace(s))
|
||||
.Select(static s => s.Trim().Trim('/', '\\')));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UploadFileToBucketArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var sourceFilePath = executeContext.GetVariable<string>(executeContext.Arguments.FilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(sourceFilePath, nameof(sourceFilePath));
|
||||
var fileName = Path.GetFileName(sourceFilePath);
|
||||
var destinationKey = string.Join('/', new[] { executeContext.Arguments.DestinationRoute, fileName }
|
||||
.Where(static s => !string.IsNullOrWhiteSpace(s))
|
||||
.Select(static s => s.Trim().Trim('/', '\\')));
|
||||
|
||||
try
|
||||
{
|
||||
await storageHandler.UploadFileAsync(
|
||||
sourceFilePath,
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
destinationKey,
|
||||
executeContext.CancellationToken);
|
||||
return executeContext.CompletedWithVariables(new UploadFileToBucketLog(
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
destinationKey));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to upload file to bucket");
|
||||
throw;
|
||||
}
|
||||
await storageHandler.UploadFileAsync(
|
||||
sourceFilePath,
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
destinationKey,
|
||||
executeContext.CancellationToken);
|
||||
return executeContext.CompletedWithVariables(new UploadFileToBucketLog(
|
||||
executeContext.Arguments.DestinationBucket,
|
||||
destinationKey));
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UploadFileToBucketLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
await storageHandler.RemoveFileAsync(
|
||||
compensateContext.Log.DestinationBucket,
|
||||
compensateContext.Log.DestinationKey,
|
||||
compensateContext.CancellationToken);
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Error compensating file upload for {Bucket}/{Key}",
|
||||
compensateContext.Log.DestinationBucket,
|
||||
compensateContext.Log.DestinationKey);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
logger.LogError(exception, "Failed to upload file to bucket");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UploadFileToBucketLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
await storageHandler.RemoveFileAsync(
|
||||
compensateContext.Log.DestinationBucket,
|
||||
compensateContext.Log.DestinationKey,
|
||||
compensateContext.CancellationToken);
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Error compensating file upload for {Bucket}/{Key}",
|
||||
compensateContext.Log.DestinationBucket,
|
||||
compensateContext.Log.DestinationKey);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+40
-41
@@ -2,50 +2,49 @@ using MassTransit;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
|
||||
internal class GeneratePictureWorkflowPathsActivity(
|
||||
ILogger<GeneratePictureWorkflowPathsActivity> logger)
|
||||
: IExecuteActivity<GeneratePictureWorkflowPathsArguments>
|
||||
{
|
||||
internal class GeneratePictureWorkflowPathsActivity(
|
||||
ILogger<GeneratePictureWorkflowPathsActivity> logger)
|
||||
: IExecuteActivity<GeneratePictureWorkflowPathsArguments>
|
||||
public const string ExecuteEndpointName = "generate-picture-workflow-paths";
|
||||
|
||||
internal const string ResizedPictureFileExtension = ".webp";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<GeneratePictureWorkflowPathsArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "generate-picture-workflow-paths";
|
||||
|
||||
internal const string ResizedPictureFileExtension = ".webp";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<GeneratePictureWorkflowPathsArguments> executeContext)
|
||||
try
|
||||
{
|
||||
try
|
||||
var workingDirectory = Path.Combine(executeContext.Arguments.TemporaryRootDirectory, Guid.NewGuid().ToString());
|
||||
|
||||
var sourceFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + Path.GetExtension(executeContext.Arguments.SourceKey));
|
||||
var smallPictureFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + ResizedPictureFileExtension);
|
||||
var mediumPictureFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + ResizedPictureFileExtension);
|
||||
var largePictureFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + ResizedPictureFileExtension);
|
||||
|
||||
Directory.CreateDirectory(workingDirectory);
|
||||
|
||||
logger.LogDebug("Generated picture workflow paths in {WorkingDirectory}",
|
||||
workingDirectory);
|
||||
return executeContext.CompletedWithVariables(new Dictionary<string, object>
|
||||
{
|
||||
var workingDirectory = Path.Combine(executeContext.Arguments.TemporaryRootDirectory, Guid.NewGuid().ToString());
|
||||
|
||||
var sourceFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + Path.GetExtension(executeContext.Arguments.SourceKey));
|
||||
var smallPictureFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + ResizedPictureFileExtension);
|
||||
var mediumPictureFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + ResizedPictureFileExtension);
|
||||
var largePictureFilePath = Path.Combine(
|
||||
workingDirectory, Guid.NewGuid().ToString() + ResizedPictureFileExtension);
|
||||
|
||||
Directory.CreateDirectory(workingDirectory);
|
||||
|
||||
logger.LogDebug("Generated picture workflow paths in {WorkingDirectory}",
|
||||
workingDirectory);
|
||||
return executeContext.CompletedWithVariables(new Dictionary<string, object>
|
||||
{
|
||||
[RoutingSlipVariableNames.Workflow.TemporalDirectory] = workingDirectory,
|
||||
[RoutingSlipVariableNames.Picture.OriginalFilePath] = sourceFilePath,
|
||||
[RoutingSlipVariableNames.Picture.SmallResizedFilePath] = smallPictureFilePath,
|
||||
[RoutingSlipVariableNames.Picture.MediumResizedFilePath] = mediumPictureFilePath,
|
||||
[RoutingSlipVariableNames.Picture.LargeResizedFilePath] = largePictureFilePath
|
||||
} );
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to generate picture workflow paths for {SourceKey}",
|
||||
executeContext.Arguments.SourceKey);
|
||||
throw;
|
||||
}
|
||||
[RoutingSlipVariableNames.Workflow.TemporalDirectory] = workingDirectory,
|
||||
[RoutingSlipVariableNames.Picture.OriginalFilePath] = sourceFilePath,
|
||||
[RoutingSlipVariableNames.Picture.SmallResizedFilePath] = smallPictureFilePath,
|
||||
[RoutingSlipVariableNames.Picture.MediumResizedFilePath] = mediumPictureFilePath,
|
||||
[RoutingSlipVariableNames.Picture.LargeResizedFilePath] = largePictureFilePath
|
||||
});
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to generate picture workflow paths for {SourceKey}",
|
||||
executeContext.Arguments.SourceKey);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+55
-56
@@ -4,69 +4,68 @@ using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
|
||||
internal class ResizePictureActivity(
|
||||
IPictureService pictureHandler,
|
||||
ILogger<ResizePictureActivity> logger)
|
||||
: IActivity<ResizePictureLocalArguments, ResizePictureLog>
|
||||
{
|
||||
internal class ResizePictureActivity(
|
||||
IPictureService pictureHandler,
|
||||
ILogger<ResizePictureActivity> logger)
|
||||
: IActivity<ResizePictureLocalArguments, ResizePictureLog>
|
||||
public const string ExecuteEndpointName = "resize-picture";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<ResizePictureLocalArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "resize-picture";
|
||||
var sourceFilePath = executeContext.GetVariable<string>(executeContext.Arguments.SourceFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(sourceFilePath, nameof(sourceFilePath));
|
||||
var destinationFilePath = executeContext.GetVariable<string>(executeContext.Arguments.DestinationFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(destinationFilePath, nameof(destinationFilePath));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<ResizePictureLocalArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var sourceFilePath = executeContext.GetVariable<string>(executeContext.Arguments.SourceFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(sourceFilePath, nameof(sourceFilePath));
|
||||
var destinationFilePath = executeContext.GetVariable<string>(executeContext.Arguments.DestinationFilePathVariable);
|
||||
ArgumentNullException.ThrowIfNull(destinationFilePath, nameof(destinationFilePath));
|
||||
|
||||
try
|
||||
if (!File.Exists(sourceFilePath))
|
||||
{
|
||||
if (!File.Exists(sourceFilePath))
|
||||
{
|
||||
logger.LogWarning("Source file not found: {SourceFilePath}", sourceFilePath);
|
||||
throw new FileNotFoundException($"Source file not found: {sourceFilePath}");
|
||||
}
|
||||
|
||||
await using var fileStream = File.OpenRead(sourceFilePath);
|
||||
|
||||
await using var resizedPicture = await pictureHandler.ResizePictureAsWebpAsync(
|
||||
fileStream,
|
||||
executeContext.Arguments.Width,
|
||||
executeContext.Arguments.Height,
|
||||
executeContext.CancellationToken);
|
||||
|
||||
var destinationDirectory = Path.GetDirectoryName(destinationFilePath);
|
||||
if (!string.IsNullOrEmpty(destinationDirectory))
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
|
||||
await using var destinationStream = File.Create(destinationFilePath);
|
||||
await resizedPicture.CopyToAsync(destinationStream, executeContext.CancellationToken);
|
||||
|
||||
logger.LogDebug("Resized picture from {SourceFilePath} to {DestinationFilePath}",
|
||||
sourceFilePath,
|
||||
destinationFilePath);
|
||||
return executeContext.Completed(new ResizePictureLog(destinationFilePath));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to resize picture {SourceFilePath}", sourceFilePath);
|
||||
throw;
|
||||
logger.LogWarning("Source file not found: {SourceFilePath}", sourceFilePath);
|
||||
throw new FileNotFoundException($"Source file not found: {sourceFilePath}");
|
||||
}
|
||||
|
||||
await using var fileStream = File.OpenRead(sourceFilePath);
|
||||
|
||||
await using var resizedPicture = await pictureHandler.ResizePictureAsWebpAsync(
|
||||
fileStream,
|
||||
executeContext.Arguments.Width,
|
||||
executeContext.Arguments.Height,
|
||||
executeContext.CancellationToken);
|
||||
|
||||
var destinationDirectory = Path.GetDirectoryName(destinationFilePath);
|
||||
if (!string.IsNullOrEmpty(destinationDirectory))
|
||||
Directory.CreateDirectory(destinationDirectory);
|
||||
|
||||
await using var destinationStream = File.Create(destinationFilePath);
|
||||
await resizedPicture.CopyToAsync(destinationStream, executeContext.CancellationToken);
|
||||
|
||||
logger.LogDebug("Resized picture from {SourceFilePath} to {DestinationFilePath}",
|
||||
sourceFilePath,
|
||||
destinationFilePath);
|
||||
return executeContext.Completed(new ResizePictureLog(destinationFilePath));
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<ResizePictureLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate resized file {DestinationFilePath}", compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
logger.LogError(exception, "Failed to resize picture {SourceFilePath}", sourceFilePath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<CompensationResult> Compensate(CompensateContext<ResizePictureLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Compensated());
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate resized file {DestinationFilePath}", compensateContext.Log.DestinationFilePath);
|
||||
return Task.FromResult(compensateContext.Failed(exception));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+84
-85
@@ -6,108 +6,107 @@ using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
|
||||
internal class UpdateAlbumPictureActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdateAlbumPictureActivity> logger)
|
||||
: IActivity<UpdateAlbumPictureArguments, UpdateAlbumPictureLog>
|
||||
{
|
||||
internal class UpdateAlbumPictureActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdateAlbumPictureActivity> logger)
|
||||
: IActivity<UpdateAlbumPictureArguments, UpdateAlbumPictureLog>
|
||||
public const string ExecuteEndpointName = "update-album-picture";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdateAlbumPictureArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "update-album-picture";
|
||||
var smallResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.SmallPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(smallResizedVariable, nameof(smallResizedVariable));
|
||||
var mediumResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.MediumPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(mediumResizedVariable, nameof(mediumResizedVariable));
|
||||
var largeResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.LargePictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(largeResizedVariable, nameof(largeResizedVariable));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdateAlbumPictureArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var smallResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.SmallPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(smallResizedVariable, nameof(smallResizedVariable));
|
||||
var mediumResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.MediumPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(mediumResizedVariable, nameof(mediumResizedVariable));
|
||||
var largeResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.LargePictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(largeResizedVariable, nameof(largeResizedVariable));
|
||||
var album = await database.Albums.FindAsync(
|
||||
[executeContext.Arguments.AlbumId],
|
||||
cancellationToken: executeContext.CancellationToken);
|
||||
|
||||
try
|
||||
if (album == null)
|
||||
{
|
||||
var album = await database.Albums.FindAsync(
|
||||
[executeContext.Arguments.AlbumId],
|
||||
cancellationToken: executeContext.CancellationToken);
|
||||
|
||||
if (album == null)
|
||||
{
|
||||
logger.LogWarning("Album {AlbumId} not found",
|
||||
executeContext.Arguments.AlbumId);
|
||||
throw new InvalidOperationException($"Album with id {executeContext.Arguments.AlbumId} not found");
|
||||
}
|
||||
|
||||
if (album.Pictures == null)
|
||||
{
|
||||
logger.LogWarning("Album {AlbumId} has no pending picture upload",
|
||||
executeContext.Arguments.AlbumId);
|
||||
throw new InvalidOperationException($"Album with id {executeContext.Arguments.AlbumId} has no pending picture upload");
|
||||
}
|
||||
|
||||
var log = new UpdateAlbumPictureLog(
|
||||
album.Id,
|
||||
album.Pictures.OriginalName,
|
||||
album.Pictures.SmallName,
|
||||
album.Pictures.MediumName,
|
||||
album.Pictures.LargeName);
|
||||
|
||||
album.Pictures.OriginalName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
|
||||
album.Pictures.SmallName = Path.GetFileName(smallResizedVariable);
|
||||
album.Pictures.MediumName = Path.GetFileName(mediumResizedVariable);
|
||||
album.Pictures.LargeName = Path.GetFileName(largeResizedVariable);
|
||||
|
||||
database.Albums.Update(album);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated album {AlbumId} pictures",
|
||||
logger.LogWarning("Album {AlbumId} not found",
|
||||
executeContext.Arguments.AlbumId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new AlbumPictureProcessed(executeContext.Arguments.AlbumId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed();
|
||||
throw new InvalidOperationException($"Album with id {executeContext.Arguments.AlbumId} not found");
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
if (album.Pictures == null)
|
||||
{
|
||||
logger.LogError(exception, "Failed to update album {AlbumId} pictures",
|
||||
logger.LogWarning("Album {AlbumId} has no pending picture upload",
|
||||
executeContext.Arguments.AlbumId);
|
||||
throw;
|
||||
throw new InvalidOperationException($"Album with id {executeContext.Arguments.AlbumId} has no pending picture upload");
|
||||
}
|
||||
|
||||
var log = new UpdateAlbumPictureLog(
|
||||
album.Id,
|
||||
album.Pictures.OriginalName,
|
||||
album.Pictures.SmallName,
|
||||
album.Pictures.MediumName,
|
||||
album.Pictures.LargeName);
|
||||
|
||||
album.Pictures.OriginalName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
|
||||
album.Pictures.SmallName = Path.GetFileName(smallResizedVariable);
|
||||
album.Pictures.MediumName = Path.GetFileName(mediumResizedVariable);
|
||||
album.Pictures.LargeName = Path.GetFileName(largeResizedVariable);
|
||||
|
||||
database.Albums.Update(album);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated album {AlbumId} pictures",
|
||||
executeContext.Arguments.AlbumId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new AlbumPictureProcessed(executeContext.Arguments.AlbumId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdateAlbumPictureLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
logger.LogError(exception, "Failed to update album {AlbumId} pictures",
|
||||
executeContext.Arguments.AlbumId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdateAlbumPictureLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
var album = await database.Albums.FindAsync(
|
||||
[compensateContext.Log.AlbumId],
|
||||
cancellationToken: compensateContext.CancellationToken);
|
||||
|
||||
if (album == null)
|
||||
{
|
||||
var album = await database.Albums.FindAsync(
|
||||
[compensateContext.Log.AlbumId],
|
||||
cancellationToken: compensateContext.CancellationToken);
|
||||
|
||||
if (album == null)
|
||||
{
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
|
||||
album.Pictures = new AlbumPictures
|
||||
{
|
||||
OriginalName = compensateContext.Log.PreviousOriginalPictureKey,
|
||||
SmallName = compensateContext.Log.PreviousSmallPictureKey,
|
||||
MediumName = compensateContext.Log.PreviousMediumPictureKey,
|
||||
LargeName = compensateContext.Log.PreviousLargePictureKey
|
||||
};
|
||||
|
||||
database.Albums.Update(album);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
album.Pictures = new AlbumPictures
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate album {AlbumId} pictures", compensateContext.Log.AlbumId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
OriginalName = compensateContext.Log.PreviousOriginalPictureKey,
|
||||
SmallName = compensateContext.Log.PreviousSmallPictureKey,
|
||||
MediumName = compensateContext.Log.PreviousMediumPictureKey,
|
||||
LargeName = compensateContext.Log.PreviousLargePictureKey
|
||||
};
|
||||
|
||||
database.Albums.Update(album);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate album {AlbumId} pictures", compensateContext.Log.AlbumId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+89
-90
@@ -6,108 +6,107 @@ using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
|
||||
internal class UpdatePlayListPictureActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdatePlayListPictureActivity> logger)
|
||||
: IActivity<UpdatePlayListPictureArguments, UpdatePlayListPictureLog>
|
||||
{
|
||||
internal class UpdatePlayListPictureActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdatePlayListPictureActivity> logger)
|
||||
: IActivity<UpdatePlayListPictureArguments, UpdatePlayListPictureLog>
|
||||
public const string ExecuteEndpointName = "update-play-list-picture";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdatePlayListPictureArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "update-play-list-picture";
|
||||
var smallResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.SmallPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(smallResizedVariable, nameof(smallResizedVariable));
|
||||
var mediumResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.MediumPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(mediumResizedVariable, nameof(mediumResizedVariable));
|
||||
var largeResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.LargePictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(largeResizedVariable, nameof(largeResizedVariable));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdatePlayListPictureArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var smallResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.SmallPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(smallResizedVariable, nameof(smallResizedVariable));
|
||||
var mediumResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.MediumPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(mediumResizedVariable, nameof(mediumResizedVariable));
|
||||
var largeResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.LargePictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(largeResizedVariable, nameof(largeResizedVariable));
|
||||
var playList = await database.PlayLists.FindAsync(
|
||||
[executeContext.Arguments.PlayListId],
|
||||
cancellationToken: executeContext.CancellationToken);
|
||||
|
||||
try
|
||||
if (playList == null)
|
||||
{
|
||||
var playList = await database.PlayLists.FindAsync(
|
||||
[executeContext.Arguments.PlayListId],
|
||||
cancellationToken: executeContext.CancellationToken);
|
||||
|
||||
if (playList == null)
|
||||
{
|
||||
logger.LogWarning("Playlist {PlayListId} not found",
|
||||
executeContext.Arguments.PlayListId);
|
||||
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} not found");
|
||||
}
|
||||
|
||||
if (playList.Pictures == null)
|
||||
{
|
||||
logger.LogWarning("Playlist {PlayListId} has no pending picture upload",
|
||||
executeContext.Arguments.PlayListId);
|
||||
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} has no pending picture upload");
|
||||
}
|
||||
|
||||
var log = new UpdatePlayListPictureLog(
|
||||
playList.Id,
|
||||
playList.Pictures.OriginalName,
|
||||
playList.Pictures.SmallName,
|
||||
playList.Pictures.MediumName,
|
||||
playList.Pictures.LargeName);
|
||||
|
||||
playList.Pictures.OriginalName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
|
||||
playList.Pictures.SmallName = Path.GetFileName(smallResizedVariable);
|
||||
playList.Pictures.MediumName = Path.GetFileName(mediumResizedVariable);
|
||||
playList.Pictures.LargeName = Path.GetFileName(largeResizedVariable);
|
||||
|
||||
database.PlayLists.Update(playList);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated playlist {PlayListId} pictures",
|
||||
logger.LogWarning("Playlist {PlayListId} not found",
|
||||
executeContext.Arguments.PlayListId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new PlayListPictureProcessed(executeContext.Arguments.PlayListId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed();
|
||||
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} not found");
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
if (playList.Pictures == null)
|
||||
{
|
||||
logger.LogError(exception, "Failed to update playlist {PlayListId} pictures",
|
||||
logger.LogWarning("Playlist {PlayListId} has no pending picture upload",
|
||||
executeContext.Arguments.PlayListId);
|
||||
throw;
|
||||
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} has no pending picture upload");
|
||||
}
|
||||
|
||||
var log = new UpdatePlayListPictureLog(
|
||||
playList.Id,
|
||||
playList.Pictures.OriginalName,
|
||||
playList.Pictures.SmallName,
|
||||
playList.Pictures.MediumName,
|
||||
playList.Pictures.LargeName);
|
||||
|
||||
playList.Pictures.OriginalName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
|
||||
playList.Pictures.SmallName = Path.GetFileName(smallResizedVariable);
|
||||
playList.Pictures.MediumName = Path.GetFileName(mediumResizedVariable);
|
||||
playList.Pictures.LargeName = Path.GetFileName(largeResizedVariable);
|
||||
|
||||
database.PlayLists.Update(playList);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated playlist {PlayListId} pictures",
|
||||
executeContext.Arguments.PlayListId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new PlayListPictureProcessed(executeContext.Arguments.PlayListId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdatePlayListPictureLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
var playList = await database.PlayLists.FindAsync(
|
||||
[compensateContext.Log.PlayListId],
|
||||
cancellationToken: compensateContext.CancellationToken);
|
||||
|
||||
if (playList == null)
|
||||
{
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
|
||||
playList.Pictures = new PlayListPictures
|
||||
{
|
||||
OriginalName = compensateContext.Log.PreviousOriginalPictureKey,
|
||||
SmallName = compensateContext.Log.PreviousSmallPictureKey,
|
||||
MediumName = compensateContext.Log.PreviousMediumPictureKey,
|
||||
LargeName = compensateContext.Log.PreviousLargePictureKey
|
||||
};
|
||||
|
||||
database.PlayLists.Update(playList);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate playlist {PlayListId} pictures", compensateContext.Log.PlayListId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
logger.LogError(exception, "Failed to update playlist {PlayListId} pictures",
|
||||
executeContext.Arguments.PlayListId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdatePlayListPictureLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
var playList = await database.PlayLists.FindAsync(
|
||||
[compensateContext.Log.PlayListId],
|
||||
cancellationToken: compensateContext.CancellationToken);
|
||||
|
||||
if (playList == null)
|
||||
{
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
|
||||
playList.Pictures = new PlayListPictures
|
||||
{
|
||||
OriginalName = compensateContext.Log.PreviousOriginalPictureKey,
|
||||
SmallName = compensateContext.Log.PreviousSmallPictureKey,
|
||||
MediumName = compensateContext.Log.PreviousMediumPictureKey,
|
||||
LargeName = compensateContext.Log.PreviousLargePictureKey
|
||||
};
|
||||
|
||||
database.PlayLists.Update(playList);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate playlist {PlayListId} pictures", compensateContext.Log.PlayListId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+82
-83
@@ -6,98 +6,97 @@ using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
|
||||
internal class UpdateTrackPictureActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdateTrackPictureActivity> logger)
|
||||
: IActivity<UpdateTrackPictureArguments, UpdateTrackPictureLog>
|
||||
{
|
||||
internal class UpdateTrackPictureActivity(
|
||||
IDatabase database,
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<UpdateTrackPictureActivity> logger)
|
||||
: IActivity<UpdateTrackPictureArguments, UpdateTrackPictureLog>
|
||||
public const string ExecuteEndpointName = "update-track-picture";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdateTrackPictureArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "update-track-picture";
|
||||
var smallResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.SmallPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(smallResizedVariable, nameof(smallResizedVariable));
|
||||
var mediumResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.MediumPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(mediumResizedVariable, nameof(mediumResizedVariable));
|
||||
var largeResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.LargePictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(largeResizedVariable, nameof(largeResizedVariable));
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<UpdateTrackPictureArguments> executeContext)
|
||||
try
|
||||
{
|
||||
var smallResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.SmallPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(smallResizedVariable, nameof(smallResizedVariable));
|
||||
var mediumResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.MediumPictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(mediumResizedVariable, nameof(mediumResizedVariable));
|
||||
var largeResizedVariable = executeContext.GetVariable<string>(executeContext.Arguments.LargePictureVariable);
|
||||
ArgumentNullException.ThrowIfNull(largeResizedVariable, nameof(largeResizedVariable));
|
||||
var track = await database.Tracks.FindAsync(
|
||||
[executeContext.Arguments.TrackId],
|
||||
cancellationToken: executeContext.CancellationToken);
|
||||
|
||||
try
|
||||
if (track == null)
|
||||
{
|
||||
var track = await database.Tracks.FindAsync(
|
||||
[executeContext.Arguments.TrackId],
|
||||
cancellationToken: executeContext.CancellationToken);
|
||||
|
||||
if (track == null)
|
||||
{
|
||||
logger.LogWarning("Track {TrackId} not found",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found");
|
||||
}
|
||||
|
||||
var log = new UpdateTrackPictureLog(
|
||||
track.Id,
|
||||
track.Pictures.OriginalName,
|
||||
track.Pictures.SmallName,
|
||||
track.Pictures.MediumName,
|
||||
track.Pictures.LargeName);
|
||||
|
||||
track.Pictures.OriginalName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
|
||||
track.Pictures.SmallName = Path.GetFileName(smallResizedVariable);
|
||||
track.Pictures.MediumName = Path.GetFileName(mediumResizedVariable);
|
||||
track.Pictures.LargeName = Path.GetFileName(largeResizedVariable);
|
||||
track.Pictures.ProcessingStatus = ProcessingStatus.Completed;
|
||||
|
||||
database.Tracks.Update(track);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated track {TrackId} pictures",
|
||||
logger.LogWarning("Track {TrackId} not found",
|
||||
executeContext.Arguments.TrackId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new TrackPictureProcessed(executeContext.Arguments.TrackId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to update track {TrackId} pictures",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found");
|
||||
}
|
||||
|
||||
var log = new UpdateTrackPictureLog(
|
||||
track.Id,
|
||||
track.Pictures.OriginalName,
|
||||
track.Pictures.SmallName,
|
||||
track.Pictures.MediumName,
|
||||
track.Pictures.LargeName);
|
||||
|
||||
track.Pictures.OriginalName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
|
||||
track.Pictures.SmallName = Path.GetFileName(smallResizedVariable);
|
||||
track.Pictures.MediumName = Path.GetFileName(mediumResizedVariable);
|
||||
track.Pictures.LargeName = Path.GetFileName(largeResizedVariable);
|
||||
track.Pictures.ProcessingStatus = ProcessingStatus.Completed;
|
||||
|
||||
database.Tracks.Update(track);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Updated track {TrackId} pictures",
|
||||
executeContext.Arguments.TrackId);
|
||||
|
||||
await publishEndpoint.Publish(
|
||||
new TrackPictureProcessed(executeContext.Arguments.TrackId),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdateTrackPictureLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
var track = await database.Tracks.FindAsync(
|
||||
[compensateContext.Log.TrackId],
|
||||
cancellationToken: compensateContext.CancellationToken);
|
||||
|
||||
if (track == null)
|
||||
return compensateContext.Compensated();
|
||||
|
||||
track.Pictures.OriginalName = compensateContext.Log.PreviousOriginalPictureKey;
|
||||
track.Pictures.SmallName = compensateContext.Log.PreviousSmallPictureKey;
|
||||
track.Pictures.MediumName = compensateContext.Log.PreviousMediumPictureKey;
|
||||
track.Pictures.LargeName = compensateContext.Log.PreviousLargePictureKey;
|
||||
track.Pictures.ProcessingStatus = ProcessingStatus.Failed;
|
||||
|
||||
database.Tracks.Update(track);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate track {TrackId} pictures", compensateContext.Log.TrackId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
logger.LogError(exception, "Failed to update track {TrackId} pictures",
|
||||
executeContext.Arguments.TrackId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<UpdateTrackPictureLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
var track = await database.Tracks.FindAsync(
|
||||
[compensateContext.Log.TrackId],
|
||||
cancellationToken: compensateContext.CancellationToken);
|
||||
|
||||
if (track == null)
|
||||
return compensateContext.Compensated();
|
||||
|
||||
track.Pictures.OriginalName = compensateContext.Log.PreviousOriginalPictureKey;
|
||||
track.Pictures.SmallName = compensateContext.Log.PreviousSmallPictureKey;
|
||||
track.Pictures.MediumName = compensateContext.Log.PreviousMediumPictureKey;
|
||||
track.Pictures.LargeName = compensateContext.Log.PreviousLargePictureKey;
|
||||
track.Pictures.ProcessingStatus = ProcessingStatus.Failed;
|
||||
|
||||
database.Tracks.Update(track);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.LogError(exception, "Failed to compensate track {TrackId} pictures", compensateContext.Log.TrackId);
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-22
@@ -4,33 +4,32 @@ using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
|
||||
internal class DeletePlayListFromDbActivity(
|
||||
IDatabase database,
|
||||
ILogger<DeletePlayListFromDbActivity> logger)
|
||||
: IExecuteActivity<DeletePlayListFromDbArguments>
|
||||
{
|
||||
internal class DeletePlayListFromDbActivity(
|
||||
IDatabase database,
|
||||
ILogger<DeletePlayListFromDbActivity> logger)
|
||||
: IExecuteActivity<DeletePlayListFromDbArguments>
|
||||
public const string ExecuteEndpointName = "delete-play-list-from-db";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DeletePlayListFromDbArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "delete-play-list-from-db";
|
||||
var playList = await database.PlayLists
|
||||
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DeletePlayListFromDbArguments> executeContext)
|
||||
if (playList == null)
|
||||
{
|
||||
var playList = await database.PlayLists
|
||||
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||
|
||||
if (playList == null)
|
||||
{
|
||||
logger.LogInformation(
|
||||
"PlayList {PlayListId} not found while deleting from DB, skipping",
|
||||
executeContext.Arguments.PlayListId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
database.PlayLists.Remove(playList);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Deleted playlist {PlayListId} from DB", playList.Id);
|
||||
logger.LogInformation(
|
||||
"PlayList {PlayListId} not found while deleting from DB, skipping",
|
||||
executeContext.Arguments.PlayListId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
database.PlayLists.Remove(playList);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Deleted playlist {PlayListId} from DB", playList.Id);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+17
-18
@@ -5,28 +5,27 @@ using Musify.Application.Contracts;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
|
||||
internal class MarkPlayListAsFailedActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkPlayListAsFailedActivity> logger)
|
||||
: IExecuteActivity<MarkPlayListAsFailedArguments>
|
||||
{
|
||||
internal class MarkPlayListAsFailedActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkPlayListAsFailedActivity> logger)
|
||||
: IExecuteActivity<MarkPlayListAsFailedArguments>
|
||||
public const string ExecuteEndpointName = "mark-play-list-as-failed";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkPlayListAsFailedArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "mark-play-list-as-failed";
|
||||
var playList = await database.PlayLists
|
||||
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkPlayListAsFailedArguments> executeContext)
|
||||
if (playList != null)
|
||||
{
|
||||
var playList = await database.PlayLists
|
||||
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||
|
||||
if (playList != null)
|
||||
{
|
||||
playList.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
logger.LogInformation("Marked playlist {PlayListId} as failed", executeContext.Arguments.PlayListId);
|
||||
}
|
||||
|
||||
return executeContext.Completed();
|
||||
playList.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
logger.LogInformation("Marked playlist {PlayListId} as failed", executeContext.Arguments.PlayListId);
|
||||
}
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+23
-24
@@ -1,37 +1,36 @@
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
|
||||
internal class MarkPlayListAsRemovingActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkPlayListAsRemovingActivity> logger)
|
||||
: IExecuteActivity<MarkPlayListAsRemovingArguments>
|
||||
{
|
||||
internal class MarkPlayListAsRemovingActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkPlayListAsRemovingActivity> logger)
|
||||
: IExecuteActivity<MarkPlayListAsRemovingArguments>
|
||||
public const string ExecuteEndpointName = "mark-play-list-as-removing";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkPlayListAsRemovingArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "mark-play-list-as-removing";
|
||||
var playList = await database.PlayLists
|
||||
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkPlayListAsRemovingArguments> executeContext)
|
||||
if (playList == null)
|
||||
{
|
||||
var playList = await database.PlayLists
|
||||
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||
|
||||
if (playList == null)
|
||||
{
|
||||
logger.LogInformation(
|
||||
"PlayList {PlayListId} not found while marking as removing, skipping",
|
||||
executeContext.Arguments.PlayListId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
playList.LifeCycleStatus = LifeCycleStatus.Removing;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Marked playlist {PlayListId} as removing", playList.Id);
|
||||
logger.LogInformation(
|
||||
"PlayList {PlayListId} not found while marking as removing, skipping",
|
||||
executeContext.Arguments.PlayListId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
playList.LifeCycleStatus = LifeCycleStatus.Removing;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Marked playlist {PlayListId} as removing", playList.Id);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+21
-22
@@ -3,32 +3,31 @@ using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
|
||||
internal class PublishPlayListPictureProcessingEventActivity(
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<PublishPlayListPictureProcessingEventActivity> logger)
|
||||
: IExecuteActivity<PublishPlayListPictureProcessingEventArguments>
|
||||
{
|
||||
internal class PublishPlayListPictureProcessingEventActivity(
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<PublishPlayListPictureProcessingEventActivity> logger)
|
||||
: IExecuteActivity<PublishPlayListPictureProcessingEventArguments>
|
||||
public const string ExecuteEndpointName = "publish-play-list-picture-processing-event";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<PublishPlayListPictureProcessingEventArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "publish-play-list-picture-processing-event";
|
||||
var arguments = executeContext.Arguments;
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<PublishPlayListPictureProcessingEventArguments> executeContext)
|
||||
{
|
||||
var arguments = executeContext.Arguments;
|
||||
await publishEndpoint.Publish(
|
||||
new UpdatePlayListPictureEvent(
|
||||
arguments.PlayListId,
|
||||
arguments.Bucket,
|
||||
arguments.FinalPictureKey,
|
||||
arguments.Small,
|
||||
arguments.Medium,
|
||||
arguments.Large),
|
||||
executeContext.CancellationToken);
|
||||
|
||||
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);
|
||||
|
||||
logger.LogInformation("Published picture processing event for playlist {PlayListId}", arguments.PlayListId);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+21
-22
@@ -4,33 +4,32 @@ using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
|
||||
internal class DeleteTrackFromDbActivity(
|
||||
IDatabase database,
|
||||
ILogger<DeleteTrackFromDbActivity> logger)
|
||||
: IExecuteActivity<DeleteTrackFromDbArguments>
|
||||
{
|
||||
internal class DeleteTrackFromDbActivity(
|
||||
IDatabase database,
|
||||
ILogger<DeleteTrackFromDbActivity> logger)
|
||||
: IExecuteActivity<DeleteTrackFromDbArguments>
|
||||
public const string ExecuteEndpointName = "delete-track-from-db";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DeleteTrackFromDbArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "delete-track-from-db";
|
||||
var track = await database.Tracks
|
||||
.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<DeleteTrackFromDbArguments> executeContext)
|
||||
if (track == null)
|
||||
{
|
||||
var track = await database.Tracks
|
||||
.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
|
||||
if (track == null)
|
||||
{
|
||||
logger.LogInformation(
|
||||
"Track {TrackId} not found while deleting from DB, skipping",
|
||||
executeContext.Arguments.TrackId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
database.Tracks.Remove(track);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Deleted track {TrackId} from DB", track.Id);
|
||||
logger.LogInformation(
|
||||
"Track {TrackId} not found while deleting from DB, skipping",
|
||||
executeContext.Arguments.TrackId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
database.Tracks.Remove(track);
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Deleted track {TrackId} from DB", track.Id);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+17
-18
@@ -5,28 +5,27 @@ using Musify.Application.Contracts;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
|
||||
internal class MarkTrackAsFailedActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkTrackAsFailedActivity> logger)
|
||||
: IExecuteActivity<MarkTrackAsFailedArguments>
|
||||
{
|
||||
internal class MarkTrackAsFailedActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkTrackAsFailedActivity> logger)
|
||||
: IExecuteActivity<MarkTrackAsFailedArguments>
|
||||
public const string ExecuteEndpointName = "mark-track-as-failed";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkTrackAsFailedArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "mark-track-as-failed";
|
||||
var track = await database.Tracks
|
||||
.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkTrackAsFailedArguments> executeContext)
|
||||
if (track != null)
|
||||
{
|
||||
var track = await database.Tracks
|
||||
.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
|
||||
if (track != null)
|
||||
{
|
||||
track.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
logger.LogInformation("Marked track {TrackId} as failed", executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
return executeContext.Completed();
|
||||
track.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
logger.LogInformation("Marked track {TrackId} as failed", executeContext.Arguments.TrackId);
|
||||
}
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+23
-24
@@ -1,37 +1,36 @@
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
|
||||
internal class MarkTrackAsRemovingActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkTrackAsRemovingActivity> logger)
|
||||
: IExecuteActivity<MarkTrackAsRemovingArguments>
|
||||
{
|
||||
internal class MarkTrackAsRemovingActivity(
|
||||
IDatabase database,
|
||||
ILogger<MarkTrackAsRemovingActivity> logger)
|
||||
: IExecuteActivity<MarkTrackAsRemovingArguments>
|
||||
public const string ExecuteEndpointName = "mark-track-as-removing";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkTrackAsRemovingArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "mark-track-as-removing";
|
||||
var track = await database.Tracks
|
||||
.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<MarkTrackAsRemovingArguments> executeContext)
|
||||
if (track == null)
|
||||
{
|
||||
var track = await database.Tracks
|
||||
.SingleOrDefaultAsync(t => t.Id == executeContext.Arguments.TrackId, executeContext.CancellationToken);
|
||||
|
||||
if (track == null)
|
||||
{
|
||||
logger.LogInformation(
|
||||
"Track {TrackId} not found while marking as removing, skipping",
|
||||
executeContext.Arguments.TrackId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
track.LifeCycleStatus = LifeCycleStatus.Removing;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Marked track {TrackId} as removing", track.Id);
|
||||
logger.LogInformation(
|
||||
"Track {TrackId} not found while marking as removing, skipping",
|
||||
executeContext.Arguments.TrackId);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
|
||||
track.LifeCycleStatus = LifeCycleStatus.Removing;
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Marked track {TrackId} as removing", track.Id);
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+29
-30
@@ -3,41 +3,40 @@ using Microsoft.Extensions.Logging;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
|
||||
internal class PublishTrackProcessingEventsActivity(
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<PublishTrackProcessingEventsActivity> logger)
|
||||
: IExecuteActivity<PublishTrackProcessingEventsArguments>
|
||||
{
|
||||
internal class PublishTrackProcessingEventsActivity(
|
||||
IPublishEndpoint publishEndpoint,
|
||||
ILogger<PublishTrackProcessingEventsActivity> logger)
|
||||
: IExecuteActivity<PublishTrackProcessingEventsArguments>
|
||||
public const string ExecuteEndpointName = "publish-track-processing-events";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<PublishTrackProcessingEventsArguments> executeContext)
|
||||
{
|
||||
public const string ExecuteEndpointName = "publish-track-processing-events";
|
||||
var arguments = executeContext.Arguments;
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<PublishTrackProcessingEventsArguments> 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 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);
|
||||
|
||||
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);
|
||||
|
||||
logger.LogInformation("Published processing events for track {TrackId}", arguments.TrackId);
|
||||
|
||||
return executeContext.Completed();
|
||||
}
|
||||
return executeContext.Completed();
|
||||
}
|
||||
}
|
||||
|
||||
+38
-39
@@ -6,57 +6,56 @@ using Musify.Domain.ValueObjects;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.UploadIntents
|
||||
{
|
||||
internal class ConsumeUploadIntentsActivity(
|
||||
IDatabase database,
|
||||
ILogger<ConsumeUploadIntentsActivity> logger)
|
||||
: IActivity<ConsumeUploadIntentsArguments, ConsumeUploadIntentsLog>
|
||||
{
|
||||
public const string ExecuteEndpointName = "consume-upload-intents";
|
||||
namespace Musify.Infrastructure.MassTransit.Activities.UploadIntents;
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<ConsumeUploadIntentsArguments> executeContext)
|
||||
internal class ConsumeUploadIntentsActivity(
|
||||
IDatabase database,
|
||||
ILogger<ConsumeUploadIntentsActivity> logger)
|
||||
: IActivity<ConsumeUploadIntentsArguments, ConsumeUploadIntentsLog>
|
||||
{
|
||||
public const string ExecuteEndpointName = "consume-upload-intents";
|
||||
|
||||
public async Task<ExecutionResult> Execute(ExecuteContext<ConsumeUploadIntentsArguments> 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<CompensationResult> Compensate(CompensateContext<ConsumeUploadIntentsLog> compensateContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
var intentIds = executeContext.Arguments.IntentIds;
|
||||
var intentIds = compensateContext.Log.IntentIds;
|
||||
|
||||
var intents = await database.UploadIntents
|
||||
.Where(i => intentIds.Contains(i.Id))
|
||||
.ToListAsync(executeContext.CancellationToken);
|
||||
.ToListAsync(compensateContext.CancellationToken);
|
||||
|
||||
foreach (var intent in intents)
|
||||
intent.Status = UploadIntentStatus.Consumed;
|
||||
intent.Status = UploadIntentStatus.Issued;
|
||||
|
||||
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||
await database.SaveChangesAsync(compensateContext.CancellationToken);
|
||||
|
||||
logger.LogInformation("Marked {Count} upload intent(s) as consumed", intents.Count);
|
||||
logger.LogInformation("Reverted {Count} upload intent(s) back to Issued", intents.Count);
|
||||
|
||||
return executeContext.Completed(new ConsumeUploadIntentsLog(intentIds));
|
||||
return compensateContext.Compensated();
|
||||
}
|
||||
|
||||
public async Task<CompensationResult> Compensate(CompensateContext<ConsumeUploadIntentsLog> compensateContext)
|
||||
catch (Exception exception)
|
||||
{
|
||||
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);
|
||||
}
|
||||
logger.LogError(exception, "Failed to compensate upload intent consumption");
|
||||
return compensateContext.Failed(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,5 +1,4 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record ConsumeUploadIntentsArguments(
|
||||
Guid[] IntentIds);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record ConsumeUploadIntentsArguments(
|
||||
Guid[] IntentIds);
|
||||
|
||||
+7
-8
@@ -1,8 +1,7 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record CopyFileInBucketArguments(
|
||||
string SourceBucket,
|
||||
string SourceKey,
|
||||
string DestinationBucket,
|
||||
string DestinationKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record CopyFileInBucketArguments(
|
||||
string SourceBucket,
|
||||
string SourceKey,
|
||||
string DestinationBucket,
|
||||
string DestinationKey);
|
||||
|
||||
+4
-5
@@ -1,5 +1,4 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
internal record DeletePlayListFromDbArguments(
|
||||
Guid PlayListId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
internal record DeletePlayListFromDbArguments(
|
||||
Guid PlayListId);
|
||||
|
||||
+4
-5
@@ -1,5 +1,4 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
internal record DeleteTrackFromDbArguments(
|
||||
Guid TrackId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
internal record DeleteTrackFromDbArguments(
|
||||
Guid TrackId);
|
||||
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record DownloadFileFromBucketArguments(
|
||||
string Bucket,
|
||||
string Key,
|
||||
string DestinationFilePathVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record DownloadFileFromBucketArguments(
|
||||
string Bucket,
|
||||
string Key,
|
||||
string DestinationFilePathVariable);
|
||||
|
||||
+5
-6
@@ -1,6 +1,5 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record DownloadFileFromUrlArguments(
|
||||
string SourceUrl,
|
||||
string DestinationFilePathVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record DownloadFileFromUrlArguments(
|
||||
string SourceUrl,
|
||||
string DestinationFilePathVariable);
|
||||
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record GenerateAudioWorkflowPathsArguments(
|
||||
Guid TrackId,
|
||||
string TemporaryRootDirectory,
|
||||
string SourceKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record GenerateAudioWorkflowPathsArguments(
|
||||
Guid TrackId,
|
||||
string TemporaryRootDirectory,
|
||||
string SourceKey);
|
||||
|
||||
+5
-6
@@ -1,6 +1,5 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record GeneratePictureWorkflowPathsArguments(
|
||||
string TemporaryRootDirectory,
|
||||
string SourceKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record GeneratePictureWorkflowPathsArguments(
|
||||
string TemporaryRootDirectory,
|
||||
string SourceKey);
|
||||
|
||||
+3
-4
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record MarkAlbumAsFailedArguments(Guid AlbumId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record MarkAlbumAsFailedArguments(Guid AlbumId);
|
||||
|
||||
+3
-4
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record MarkPlayListAsFailedArguments(Guid PlayListId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record MarkPlayListAsFailedArguments(Guid PlayListId);
|
||||
|
||||
+4
-5
@@ -1,5 +1,4 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
internal record MarkPlayListAsRemovingArguments(
|
||||
Guid PlayListId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
internal record MarkPlayListAsRemovingArguments(
|
||||
Guid PlayListId);
|
||||
|
||||
+3
-4
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record MarkTrackAsFailedArguments(Guid TrackId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record MarkTrackAsFailedArguments(Guid TrackId);
|
||||
|
||||
+4
-5
@@ -1,5 +1,4 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
internal record MarkTrackAsRemovingArguments(
|
||||
Guid TrackId);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
internal record MarkTrackAsRemovingArguments(
|
||||
Guid TrackId);
|
||||
|
||||
+9
-10
@@ -1,12 +1,11 @@
|
||||
using Musify.Application.Shared;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record PublishAlbumPictureProcessingEventArguments(
|
||||
Guid AlbumId,
|
||||
string Bucket,
|
||||
string FinalPictureKey,
|
||||
ImageSize Small,
|
||||
ImageSize Medium,
|
||||
ImageSize Large);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record PublishAlbumPictureProcessingEventArguments(
|
||||
Guid AlbumId,
|
||||
string Bucket,
|
||||
string FinalPictureKey,
|
||||
ImageSize Small,
|
||||
ImageSize Medium,
|
||||
ImageSize Large);
|
||||
|
||||
+9
-10
@@ -1,12 +1,11 @@
|
||||
using Musify.Application.Shared;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record PublishPlayListPictureProcessingEventArguments(
|
||||
Guid PlayListId,
|
||||
string Bucket,
|
||||
string FinalPictureKey,
|
||||
ImageSize Small,
|
||||
ImageSize Medium,
|
||||
ImageSize Large);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record PublishPlayListPictureProcessingEventArguments(
|
||||
Guid PlayListId,
|
||||
string Bucket,
|
||||
string FinalPictureKey,
|
||||
ImageSize Small,
|
||||
ImageSize Medium,
|
||||
ImageSize Large);
|
||||
|
||||
+11
-12
@@ -1,14 +1,13 @@
|
||||
using Musify.Application.Shared;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record PublishTrackProcessingEventsArguments(
|
||||
Guid TrackId,
|
||||
string Bucket,
|
||||
string FinalPictureKey,
|
||||
string FinalAudioKey,
|
||||
string AudioDestinationFolderKey,
|
||||
ImageSize Small,
|
||||
ImageSize Medium,
|
||||
ImageSize Large);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record PublishTrackProcessingEventsArguments(
|
||||
Guid TrackId,
|
||||
string Bucket,
|
||||
string FinalPictureKey,
|
||||
string FinalAudioKey,
|
||||
string AudioDestinationFolderKey,
|
||||
ImageSize Small,
|
||||
ImageSize Medium,
|
||||
ImageSize Large);
|
||||
|
||||
+5
-6
@@ -1,6 +1,5 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record RemoveFileFromBucketArguments(
|
||||
string Bucket,
|
||||
string Key);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record RemoveFileFromBucketArguments(
|
||||
string Bucket,
|
||||
string Key);
|
||||
|
||||
+7
-8
@@ -1,8 +1,7 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record ResizePictureLocalArguments(
|
||||
string SourceFilePathVariable,
|
||||
string DestinationFilePathVariable,
|
||||
int Width,
|
||||
int Height);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record ResizePictureLocalArguments(
|
||||
string SourceFilePathVariable,
|
||||
string DestinationFilePathVariable,
|
||||
int Width,
|
||||
int Height);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record TranscodeAudioArguments(
|
||||
Guid TrackId,
|
||||
string SourceFilePathVariable,
|
||||
string WorkingDirectoryVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record TranscodeAudioArguments(
|
||||
Guid TrackId,
|
||||
string SourceFilePathVariable,
|
||||
string WorkingDirectoryVariable);
|
||||
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record TransferFilesToBucketArguments(
|
||||
string DestinationBucket,
|
||||
string SourceDirectoryVariable,
|
||||
string DestinationKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record TransferFilesToBucketArguments(
|
||||
string DestinationBucket,
|
||||
string SourceDirectoryVariable,
|
||||
string DestinationKey);
|
||||
|
||||
+8
-9
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record UpdateAlbumPictureArguments(
|
||||
Guid AlbumId,
|
||||
string OriginalPictureKey,
|
||||
string SmallPictureVariable,
|
||||
string MediumPictureVariable,
|
||||
string LargePictureVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record UpdateAlbumPictureArguments(
|
||||
Guid AlbumId,
|
||||
string OriginalPictureKey,
|
||||
string SmallPictureVariable,
|
||||
string MediumPictureVariable,
|
||||
string LargePictureVariable);
|
||||
|
||||
+8
-9
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record UpdatePlayListPictureArguments(
|
||||
Guid PlayListId,
|
||||
string OriginalPictureKey,
|
||||
string SmallPictureVariable,
|
||||
string MediumPictureVariable,
|
||||
string LargePictureVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record UpdatePlayListPictureArguments(
|
||||
Guid PlayListId,
|
||||
string OriginalPictureKey,
|
||||
string SmallPictureVariable,
|
||||
string MediumPictureVariable,
|
||||
string LargePictureVariable);
|
||||
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record UpdateTrackAudioArguments(
|
||||
Guid TrackId,
|
||||
string AudioFolderKey,
|
||||
string DurationSecondsVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record UpdateTrackAudioArguments(
|
||||
Guid TrackId,
|
||||
string AudioFolderKey,
|
||||
string DurationSecondsVariable);
|
||||
|
||||
+8
-9
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record UpdateTrackPictureArguments(
|
||||
Guid TrackId,
|
||||
string OriginalPictureKey,
|
||||
string SmallPictureVariable,
|
||||
string MediumPictureVariable,
|
||||
string LargePictureVariable);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record UpdateTrackPictureArguments(
|
||||
Guid TrackId,
|
||||
string OriginalPictureKey,
|
||||
string SmallPictureVariable,
|
||||
string MediumPictureVariable,
|
||||
string LargePictureVariable);
|
||||
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||
{
|
||||
public record UploadFileToBucketArguments(
|
||||
string FilePathVariable,
|
||||
string DestinationBucket,
|
||||
string DestinationRoute);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Arguments;
|
||||
|
||||
public record UploadFileToBucketArguments(
|
||||
string FilePathVariable,
|
||||
string DestinationBucket,
|
||||
string DestinationRoute);
|
||||
|
||||
+22
-21
@@ -6,31 +6,32 @@ using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class AlbumProcessingFailedConsumer(IBus bus) : IConsumer<AlbumProcessingFailed>
|
||||
{
|
||||
public class AlbumProcessingFailedConsumer(IBus bus) : IConsumer<AlbumProcessingFailed>
|
||||
public async Task Consume(ConsumeContext<AlbumProcessingFailed> context)
|
||||
{
|
||||
public async 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))
|
||||
{
|
||||
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());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class CreateAlbumConsumer(
|
||||
IBus bus,
|
||||
AlbumPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<CreateAlbumResourcesEvent>
|
||||
{
|
||||
public class CreateAlbumConsumer(
|
||||
IBus bus,
|
||||
AlbumPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<CreateAlbumResourcesEvent>
|
||||
public async Task Consume(ConsumeContext<CreateAlbumResourcesEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
public async Task Consume(ConsumeContext<CreateAlbumResourcesEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class CreatePlayListConsumer(
|
||||
IBus bus,
|
||||
PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<CreatePlayListResourcesEvent>
|
||||
{
|
||||
public class CreatePlayListConsumer(
|
||||
IBus bus,
|
||||
PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<CreatePlayListResourcesEvent>
|
||||
public async Task Consume(ConsumeContext<CreatePlayListResourcesEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
public async Task Consume(ConsumeContext<CreatePlayListResourcesEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class CreateTrackConsumer(
|
||||
IBus bus,
|
||||
CreateTrackRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<CreateTrackResourcesEvent>
|
||||
{
|
||||
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();
|
||||
|
||||
public async Task Consume(ConsumeContext<CreateTrackResourcesEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-17
@@ -2,25 +2,23 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class DeletePlayListConsumer(
|
||||
IBus bus,
|
||||
DeletePlayListRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<DeletePlayListEvent>
|
||||
{
|
||||
public class DeletePlayListConsumer(
|
||||
IBus bus,
|
||||
DeletePlayListRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<DeletePlayListEvent>
|
||||
public async Task Consume(ConsumeContext<DeletePlayListEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = (await routingSlipBuilder
|
||||
.BuildAsync(
|
||||
consumeContext.Message.PlayListId,
|
||||
consumeContext.Message.UserId,
|
||||
consumeContext.CorrelationId,
|
||||
consumeContext.CancellationToken))
|
||||
.Build();
|
||||
|
||||
public async Task Consume(ConsumeContext<DeletePlayListEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = (await routingSlipBuilder
|
||||
.BuildAsync(
|
||||
consumeContext.Message.PlayListId,
|
||||
consumeContext.Message.UserId,
|
||||
consumeContext.CorrelationId,
|
||||
consumeContext.CancellationToken))
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class DeleteTrackConsumer(
|
||||
IBus bus,
|
||||
DeleteTrackRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<DeleteTrackEvent>
|
||||
{
|
||||
public class DeleteTrackConsumer(
|
||||
IBus bus,
|
||||
DeleteTrackRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<DeleteTrackEvent>
|
||||
public async Task Consume(ConsumeContext<DeleteTrackEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = (await routingSlipBuilder
|
||||
.BuildAsync(consumeContext.Message.TrackId, consumeContext.Message.UserId, consumeContext.CorrelationId, consumeContext.CancellationToken))
|
||||
.Build();
|
||||
|
||||
public async Task Consume(ConsumeContext<DeleteTrackEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = (await routingSlipBuilder
|
||||
.BuildAsync(consumeContext.Message.TrackId, consumeContext.Message.UserId, consumeContext.CorrelationId, consumeContext.CancellationToken))
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
{
|
||||
internal static class EndpointHelper
|
||||
{
|
||||
internal static Uri BuildExecuteActivityUri(string endpointName) => new($"queue:{endpointName}_execute");
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
internal static Uri BuildConsumerUri(string endpointName) => new($"queue:{endpointName}");
|
||||
}
|
||||
internal static class EndpointHelper
|
||||
{
|
||||
internal static Uri BuildExecuteActivityUri(string endpointName) => new($"queue:{endpointName}_execute");
|
||||
|
||||
internal static Uri BuildConsumerUri(string endpointName) => new($"queue:{endpointName}");
|
||||
}
|
||||
|
||||
+22
-21
@@ -6,31 +6,32 @@ using Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class PlayListProcessingFailedConsumer(IBus bus) : IConsumer<PlayListProcessingFailed>
|
||||
{
|
||||
public class PlayListProcessingFailedConsumer(IBus bus) : IConsumer<PlayListProcessingFailed>
|
||||
public async Task Consume(ConsumeContext<PlayListProcessingFailed> context)
|
||||
{
|
||||
public async 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))
|
||||
{
|
||||
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());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
+25
-24
@@ -2,35 +2,36 @@ using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Musify.Application.Events;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class ProcessingSlipFaultConsumer : IConsumer<RoutingSlipFaulted>
|
||||
{
|
||||
public class ProcessingSlipFaultConsumer : IConsumer<RoutingSlipFaulted>
|
||||
public const string QueueName = "processing-slip-fault";
|
||||
|
||||
public async Task Consume(ConsumeContext<RoutingSlipFaulted> context)
|
||||
{
|
||||
public const string QueueName = "processing-slip-fault";
|
||||
var variables = context.Message.Variables;
|
||||
|
||||
public async Task Consume(ConsumeContext<RoutingSlipFaulted> context)
|
||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.ProcessKind, out var kindObject))
|
||||
return;
|
||||
|
||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.SubjectId, out var subjectObject)
|
||||
|| !Guid.TryParse(subjectObject?.ToString(), out var subjectId))
|
||||
{
|
||||
var variables = context.Message.Variables;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.ProcessKind, out var kindObject))
|
||||
return;
|
||||
|
||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.SubjectId, out var subjectObject)
|
||||
|| !Guid.TryParse(subjectObject?.ToString(), out var subjectId))
|
||||
return;
|
||||
|
||||
switch (kindObject?.ToString())
|
||||
{
|
||||
case RoutingSlipVariableNames.ProcessKinds.TrackPicture:
|
||||
await context.Publish(new TrackPictureProcessingFailed(subjectId));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.TrackAudio:
|
||||
await context.Publish(new TrackAudioProcessingFailed(subjectId));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.PlayListPicture:
|
||||
await context.Publish(new PlayListPictureProcessingFailed(subjectId));
|
||||
break;
|
||||
}
|
||||
switch (kindObject?.ToString())
|
||||
{
|
||||
case RoutingSlipVariableNames.ProcessKinds.TrackPicture:
|
||||
await context.Publish(new TrackPictureProcessingFailed(subjectId));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.TrackAudio:
|
||||
await context.Publish(new TrackAudioProcessingFailed(subjectId));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.PlayListPicture:
|
||||
await context.Publish(new PlayListPictureProcessingFailed(subjectId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-40
@@ -1,48 +1,47 @@
|
||||
using MassTransit;
|
||||
using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class RoutingSlipCleanUpConsumer(
|
||||
ILogger<RoutingSlipCleanUpConsumer> logger) :
|
||||
IConsumer<RoutingSlipCompleted>,
|
||||
IConsumer<RoutingSlipFaulted>
|
||||
{
|
||||
public class RoutingSlipCleanUpConsumer(
|
||||
ILogger<RoutingSlipCleanUpConsumer> logger) :
|
||||
IConsumer<RoutingSlipCompleted>,
|
||||
IConsumer<RoutingSlipFaulted>
|
||||
public const string QueueName = "routing-slip-clean-up";
|
||||
|
||||
public Task Consume(ConsumeContext<RoutingSlipCompleted> consumeContext)
|
||||
=> DeleteFolder(consumeContext.Message.Variables);
|
||||
|
||||
public Task Consume(ConsumeContext<RoutingSlipFaulted> consumeContext)
|
||||
=> DeleteFolder(consumeContext.Message.Variables);
|
||||
|
||||
private Task DeleteFolder(IDictionary<string, object> variables)
|
||||
{
|
||||
public const string QueueName = "routing-slip-clean-up";
|
||||
|
||||
public Task Consume(ConsumeContext<RoutingSlipCompleted> consumeContext)
|
||||
=> DeleteFolder(consumeContext.Message.Variables);
|
||||
|
||||
public Task Consume(ConsumeContext<RoutingSlipFaulted> consumeContext)
|
||||
=> DeleteFolder(consumeContext.Message.Variables);
|
||||
|
||||
Task DeleteFolder(IDictionary<string, object> variables)
|
||||
{
|
||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.TemporalDirectory, out var pathObject))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var pathString = pathObject.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(pathString))
|
||||
return Task.CompletedTask;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(pathString, recursive: true);
|
||||
logger.LogInformation("Deleted temporal directory at path {Path}", pathString);
|
||||
}
|
||||
catch (DirectoryNotFoundException 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;
|
||||
}
|
||||
|
||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.TemporalDirectory, out var pathObject))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var pathString = pathObject.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(pathString))
|
||||
return Task.CompletedTask;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(pathString, recursive: true);
|
||||
logger.LogInformation("Deleted temporal directory at path {Path}", pathString);
|
||||
}
|
||||
catch (DirectoryNotFoundException 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;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
-27
@@ -6,37 +6,40 @@ using Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class TrackProcessingFailedConsumer(IBus bus) : IConsumer<TrackProcessingFailed>
|
||||
{
|
||||
public class TrackProcessingFailedConsumer(IBus bus) : IConsumer<TrackProcessingFailed>
|
||||
public async Task Consume(ConsumeContext<TrackProcessingFailed> context)
|
||||
{
|
||||
public async 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))
|
||||
{
|
||||
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());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class UpdateAlbumPictureConsumer(
|
||||
IBus bus,
|
||||
PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdateAlbumPictureEvent>
|
||||
{
|
||||
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();
|
||||
|
||||
public async Task Consume(ConsumeContext<UpdateAlbumPictureEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class UpdateAlbumPictureSourceConsumer(
|
||||
IBus bus,
|
||||
AlbumPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdateAlbumPictureSourceEvent>
|
||||
{
|
||||
public class UpdateAlbumPictureSourceConsumer(
|
||||
IBus bus,
|
||||
AlbumPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdateAlbumPictureSourceEvent>
|
||||
public async Task Consume(ConsumeContext<UpdateAlbumPictureSourceEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
public async Task Consume(ConsumeContext<UpdateAlbumPictureSourceEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -1,22 +1,20 @@
|
||||
using MassTransit;
|
||||
using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class UpdatePlayListPictureConsumer(
|
||||
IBus bus,
|
||||
PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdatePlayListPictureEvent>
|
||||
{
|
||||
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();
|
||||
|
||||
public async Task Consume(ConsumeContext<UpdatePlayListPictureEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-13
@@ -2,21 +2,19 @@ using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class UpdatePlayListPictureSourceConsumer(
|
||||
IBus bus,
|
||||
PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdatePlayListPictureSourceEvent>
|
||||
{
|
||||
public class UpdatePlayListPictureSourceConsumer(
|
||||
IBus bus,
|
||||
PlayListPictureSourceRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdatePlayListPictureSourceEvent>
|
||||
public async Task Consume(ConsumeContext<UpdatePlayListPictureSourceEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
public async Task Consume(ConsumeContext<UpdatePlayListPictureSourceEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -1,22 +1,20 @@
|
||||
using MassTransit;
|
||||
using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class UpdateTrackAudioConsumer(
|
||||
IBus bus,
|
||||
AudioWorkflowRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdateTrackAudioEvent>
|
||||
{
|
||||
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();
|
||||
|
||||
public async Task Consume(ConsumeContext<UpdateTrackAudioEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -1,22 +1,20 @@
|
||||
using MassTransit;
|
||||
using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||
namespace Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
public class UpdateTrackPictureConsumer(
|
||||
IBus bus,
|
||||
PictureWorkflowRoutingSlipBuilder routingSlipBuilder)
|
||||
: IConsumer<UpdateTrackPictureEvent>
|
||||
{
|
||||
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();
|
||||
|
||||
public async Task Consume(ConsumeContext<UpdateTrackPictureEvent> consumeContext)
|
||||
{
|
||||
var routingSlip = routingSlipBuilder
|
||||
.Build(consumeContext.Message, consumeContext.CorrelationId)
|
||||
.Build();
|
||||
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
await bus.Execute(routingSlip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-17
@@ -2,23 +2,22 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit
|
||||
{
|
||||
public static partial class MassTransitDependencyInjection
|
||||
{
|
||||
static void RegisterValidatedOptions<TOptions>(
|
||||
IServiceCollection services,
|
||||
IConfiguration configuration,
|
||||
string sectionName)
|
||||
where TOptions : class
|
||||
{
|
||||
services
|
||||
.AddOptionsWithValidateOnStart<TOptions>()
|
||||
.Bind(configuration.GetRequiredSection(sectionName))
|
||||
.ValidateDataAnnotations();
|
||||
namespace Musify.Infrastructure.MassTransit;
|
||||
|
||||
services.AddSingleton(serviceProvider =>
|
||||
serviceProvider.GetRequiredService<IOptions<TOptions>>().Value);
|
||||
}
|
||||
public static partial class MassTransitDependencyInjection
|
||||
{
|
||||
private static void RegisterValidatedOptions<TOptions>(
|
||||
IServiceCollection services,
|
||||
IConfiguration configuration,
|
||||
string sectionName)
|
||||
where TOptions : class
|
||||
{
|
||||
services
|
||||
.AddOptionsWithValidateOnStart<TOptions>()
|
||||
.Bind(configuration.GetRequiredSection(sectionName))
|
||||
.ValidateDataAnnotations();
|
||||
|
||||
services.AddSingleton(serviceProvider =>
|
||||
serviceProvider.GetRequiredService<IOptions<TOptions>>().Value);
|
||||
}
|
||||
}
|
||||
|
||||
+56
-57
@@ -1,9 +1,9 @@
|
||||
using MassTransit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Albums;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Audio;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
using Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
using Musify.Infrastructure.MassTransit.Activities.UploadIntents;
|
||||
@@ -12,66 +12,65 @@ using Musify.Infrastructure.MassTransit.Consumers;
|
||||
using Musify.Infrastructure.MassTransit.Logs;
|
||||
using Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit
|
||||
namespace Musify.Infrastructure.MassTransit;
|
||||
|
||||
public static partial class MassTransitDependencyInjection
|
||||
{
|
||||
public static partial class MassTransitDependencyInjection
|
||||
private static void RegisterRoutingSlipBuilders(IServiceCollection services)
|
||||
{
|
||||
static void RegisterRoutingSlipBuilders(IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<AudioWorkflowRoutingSlipBuilder>();
|
||||
services.AddScoped<PictureWorkflowRoutingSlipBuilder>();
|
||||
services.AddScoped<DeleteTrackRoutingSlipBuilder>();
|
||||
services.AddScoped<DeletePlayListRoutingSlipBuilder>();
|
||||
services.AddScoped<CreateTrackRoutingSlipBuilder>();
|
||||
services.AddScoped<PlayListPictureSourceRoutingSlipBuilder>();
|
||||
services.AddScoped<AlbumPictureSourceRoutingSlipBuilder>();
|
||||
}
|
||||
services.AddScoped<AudioWorkflowRoutingSlipBuilder>();
|
||||
services.AddScoped<PictureWorkflowRoutingSlipBuilder>();
|
||||
services.AddScoped<DeleteTrackRoutingSlipBuilder>();
|
||||
services.AddScoped<DeletePlayListRoutingSlipBuilder>();
|
||||
services.AddScoped<CreateTrackRoutingSlipBuilder>();
|
||||
services.AddScoped<PlayListPictureSourceRoutingSlipBuilder>();
|
||||
services.AddScoped<AlbumPictureSourceRoutingSlipBuilder>();
|
||||
}
|
||||
|
||||
static void RegisterConsumersAndActivities(IBusRegistrationConfigurator options)
|
||||
{
|
||||
options.AddConsumer<UpdatePlayListPictureConsumer>();
|
||||
options.AddConsumer<UpdateTrackPictureConsumer>();
|
||||
options.AddConsumer<RoutingSlipCleanUpConsumer>();
|
||||
options.AddConsumer<UpdateTrackAudioConsumer>();
|
||||
options.AddConsumer<DeleteTrackConsumer>();
|
||||
options.AddConsumer<DeletePlayListConsumer>();
|
||||
options.AddConsumer<CreateTrackConsumer>();
|
||||
options.AddConsumer<CreatePlayListConsumer>();
|
||||
options.AddConsumer<UpdatePlayListPictureSourceConsumer>();
|
||||
options.AddConsumer<ProcessingSlipFaultConsumer>();
|
||||
options.AddConsumer<TrackProcessingFailedConsumer>();
|
||||
options.AddConsumer<PlayListProcessingFailedConsumer>();
|
||||
options.AddConsumer<CreateAlbumConsumer>();
|
||||
options.AddConsumer<UpdateAlbumPictureSourceConsumer>();
|
||||
options.AddConsumer<UpdateAlbumPictureConsumer>();
|
||||
options.AddConsumer<AlbumProcessingFailedConsumer>();
|
||||
private static void RegisterConsumersAndActivities(IBusRegistrationConfigurator options)
|
||||
{
|
||||
options.AddConsumer<UpdatePlayListPictureConsumer>();
|
||||
options.AddConsumer<UpdateTrackPictureConsumer>();
|
||||
options.AddConsumer<RoutingSlipCleanUpConsumer>();
|
||||
options.AddConsumer<UpdateTrackAudioConsumer>();
|
||||
options.AddConsumer<DeleteTrackConsumer>();
|
||||
options.AddConsumer<DeletePlayListConsumer>();
|
||||
options.AddConsumer<CreateTrackConsumer>();
|
||||
options.AddConsumer<CreatePlayListConsumer>();
|
||||
options.AddConsumer<UpdatePlayListPictureSourceConsumer>();
|
||||
options.AddConsumer<ProcessingSlipFaultConsumer>();
|
||||
options.AddConsumer<TrackProcessingFailedConsumer>();
|
||||
options.AddConsumer<PlayListProcessingFailedConsumer>();
|
||||
options.AddConsumer<CreateAlbumConsumer>();
|
||||
options.AddConsumer<UpdateAlbumPictureSourceConsumer>();
|
||||
options.AddConsumer<UpdateAlbumPictureConsumer>();
|
||||
options.AddConsumer<AlbumProcessingFailedConsumer>();
|
||||
|
||||
options.AddExecuteActivity<RemoveFileFromBucketActivity, RemoveFileFromBucketArguments>();
|
||||
options.AddExecuteActivity<GenerateAudioWorkflowPathsActivity, GenerateAudioWorkflowPathsArguments>();
|
||||
options.AddExecuteActivity<GeneratePictureWorkflowPathsActivity, GeneratePictureWorkflowPathsArguments>();
|
||||
options.AddExecuteActivity<MarkTrackAsRemovingActivity, MarkTrackAsRemovingArguments>();
|
||||
options.AddExecuteActivity<DeleteTrackFromDbActivity, DeleteTrackFromDbArguments>();
|
||||
options.AddExecuteActivity<MarkPlayListAsRemovingActivity, MarkPlayListAsRemovingArguments>();
|
||||
options.AddExecuteActivity<DeletePlayListFromDbActivity, DeletePlayListFromDbArguments>();
|
||||
options.AddExecuteActivity<PublishTrackProcessingEventsActivity, PublishTrackProcessingEventsArguments>();
|
||||
options.AddExecuteActivity<PublishPlayListPictureProcessingEventActivity, PublishPlayListPictureProcessingEventArguments>();
|
||||
options.AddExecuteActivity<MarkTrackAsFailedActivity, MarkTrackAsFailedArguments>();
|
||||
options.AddExecuteActivity<MarkPlayListAsFailedActivity, MarkPlayListAsFailedArguments>();
|
||||
options.AddExecuteActivity<MarkAlbumAsFailedActivity, MarkAlbumAsFailedArguments>();
|
||||
options.AddExecuteActivity<PublishAlbumPictureProcessingEventActivity, PublishAlbumPictureProcessingEventArguments>();
|
||||
options.AddExecuteActivity<RemoveFileFromBucketActivity, RemoveFileFromBucketArguments>();
|
||||
options.AddExecuteActivity<GenerateAudioWorkflowPathsActivity, GenerateAudioWorkflowPathsArguments>();
|
||||
options.AddExecuteActivity<GeneratePictureWorkflowPathsActivity, GeneratePictureWorkflowPathsArguments>();
|
||||
options.AddExecuteActivity<MarkTrackAsRemovingActivity, MarkTrackAsRemovingArguments>();
|
||||
options.AddExecuteActivity<DeleteTrackFromDbActivity, DeleteTrackFromDbArguments>();
|
||||
options.AddExecuteActivity<MarkPlayListAsRemovingActivity, MarkPlayListAsRemovingArguments>();
|
||||
options.AddExecuteActivity<DeletePlayListFromDbActivity, DeletePlayListFromDbArguments>();
|
||||
options.AddExecuteActivity<PublishTrackProcessingEventsActivity, PublishTrackProcessingEventsArguments>();
|
||||
options.AddExecuteActivity<PublishPlayListPictureProcessingEventActivity, PublishPlayListPictureProcessingEventArguments>();
|
||||
options.AddExecuteActivity<MarkTrackAsFailedActivity, MarkTrackAsFailedArguments>();
|
||||
options.AddExecuteActivity<MarkPlayListAsFailedActivity, MarkPlayListAsFailedArguments>();
|
||||
options.AddExecuteActivity<MarkAlbumAsFailedActivity, MarkAlbumAsFailedArguments>();
|
||||
options.AddExecuteActivity<PublishAlbumPictureProcessingEventActivity, PublishAlbumPictureProcessingEventArguments>();
|
||||
|
||||
options.AddActivity<ResizePictureActivity, ResizePictureLocalArguments, ResizePictureLog>();
|
||||
options.AddActivity<UpdatePlayListPictureActivity, UpdatePlayListPictureArguments, UpdatePlayListPictureLog>();
|
||||
options.AddActivity<UpdateAlbumPictureActivity, UpdateAlbumPictureArguments, UpdateAlbumPictureLog>();
|
||||
options.AddActivity<UpdateTrackPictureActivity, UpdateTrackPictureArguments, UpdateTrackPictureLog>();
|
||||
options.AddActivity<DownloadFileFromBucketActivity, DownloadFileFromBucketArguments, DownloadFileFromBucketLog>();
|
||||
options.AddActivity<TranscodeAudioActivity, TranscodeAudioArguments, TranscodeAudioLog>();
|
||||
options.AddActivity<TransferFilesToBucketActivity, TransferFilesToBucketArguments, TransferFilesToBucketLog>();
|
||||
options.AddActivity<UpdateTrackAudioActivity, UpdateTrackAudioArguments, UpdateTrackAudioLog>();
|
||||
options.AddActivity<UploadFileToBucketActivity, UploadFileToBucketArguments, UploadFileToBucketLog>();
|
||||
options.AddActivity<CopyFileInBucketActivity, CopyFileInBucketArguments, CopyFileInBucketLog>();
|
||||
options.AddActivity<ConsumeUploadIntentsActivity, ConsumeUploadIntentsArguments, ConsumeUploadIntentsLog>();
|
||||
options.AddActivity<DownloadFileFromUrlActivity, DownloadFileFromUrlArguments, DownloadFileFromUrlLog>();
|
||||
}
|
||||
options.AddActivity<ResizePictureActivity, ResizePictureLocalArguments, ResizePictureLog>();
|
||||
options.AddActivity<UpdatePlayListPictureActivity, UpdatePlayListPictureArguments, UpdatePlayListPictureLog>();
|
||||
options.AddActivity<UpdateAlbumPictureActivity, UpdateAlbumPictureArguments, UpdateAlbumPictureLog>();
|
||||
options.AddActivity<UpdateTrackPictureActivity, UpdateTrackPictureArguments, UpdateTrackPictureLog>();
|
||||
options.AddActivity<DownloadFileFromBucketActivity, DownloadFileFromBucketArguments, DownloadFileFromBucketLog>();
|
||||
options.AddActivity<TranscodeAudioActivity, TranscodeAudioArguments, TranscodeAudioLog>();
|
||||
options.AddActivity<TransferFilesToBucketActivity, TransferFilesToBucketArguments, TransferFilesToBucketLog>();
|
||||
options.AddActivity<UpdateTrackAudioActivity, UpdateTrackAudioArguments, UpdateTrackAudioLog>();
|
||||
options.AddActivity<UploadFileToBucketActivity, UploadFileToBucketArguments, UploadFileToBucketLog>();
|
||||
options.AddActivity<CopyFileInBucketActivity, CopyFileInBucketArguments, CopyFileInBucketLog>();
|
||||
options.AddActivity<ConsumeUploadIntentsActivity, ConsumeUploadIntentsArguments, ConsumeUploadIntentsLog>();
|
||||
options.AddActivity<DownloadFileFromUrlActivity, DownloadFileFromUrlArguments, DownloadFileFromUrlLog>();
|
||||
}
|
||||
}
|
||||
|
||||
+115
-116
@@ -6,127 +6,126 @@ using Musify.Infrastructure.Configuration;
|
||||
using Musify.Infrastructure.MassTransit.Sagas;
|
||||
using Musify.Infrastructure.Persistence;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit
|
||||
namespace Musify.Infrastructure.MassTransit;
|
||||
|
||||
public static partial class MassTransitDependencyInjection
|
||||
{
|
||||
public static partial class MassTransitDependencyInjection
|
||||
public static IServiceCollection AddMassTransitClient(this IServiceCollection serviceDescriptors, IConfiguration configuration)
|
||||
{
|
||||
public static IServiceCollection AddMassTransitClient(this IServiceCollection serviceDescriptors, IConfiguration configuration)
|
||||
RegisterValidatedOptions<MassTransitConfiguration>(
|
||||
serviceDescriptors,
|
||||
configuration,
|
||||
MassTransitConfiguration.SectionName);
|
||||
|
||||
serviceDescriptors.AddScoped<IEventBus, MassTransitEventBus>();
|
||||
serviceDescriptors.AddMassTransit(options =>
|
||||
{
|
||||
RegisterValidatedOptions<MassTransitConfiguration>(
|
||||
serviceDescriptors,
|
||||
configuration,
|
||||
MassTransitConfiguration.SectionName);
|
||||
|
||||
serviceDescriptors.AddScoped<IEventBus, MassTransitEventBus>();
|
||||
serviceDescriptors.AddMassTransit(options =>
|
||||
options.AddEntityFrameworkOutbox<Database>(outbox =>
|
||||
{
|
||||
options.AddEntityFrameworkOutbox<Database>(outbox =>
|
||||
{
|
||||
outbox.UsePostgres();
|
||||
outbox.UseBusOutbox();
|
||||
outbox.UsePostgres();
|
||||
outbox.UseBusOutbox();
|
||||
|
||||
outbox.QueryDelay = TimeSpan.FromSeconds(1);
|
||||
outbox.DuplicateDetectionWindow = TimeSpan.FromMinutes(30);
|
||||
} );
|
||||
outbox.QueryDelay = TimeSpan.FromSeconds(1);
|
||||
outbox.DuplicateDetectionWindow = TimeSpan.FromMinutes(30);
|
||||
});
|
||||
|
||||
options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) =>
|
||||
ConfigureRabbitMqHost(
|
||||
busFactoryConfigurator,
|
||||
busRegistrationContext.GetRequiredService<MassTransitConfiguration>()));
|
||||
} );
|
||||
options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) =>
|
||||
ConfigureRabbitMqHost(
|
||||
busFactoryConfigurator,
|
||||
busRegistrationContext.GetRequiredService<MassTransitConfiguration>()));
|
||||
});
|
||||
|
||||
return serviceDescriptors;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddMassTransitConsumers(this IServiceCollection serviceDescriptors, IConfiguration configuration)
|
||||
{
|
||||
RegisterValidatedOptions<MassTransitConfiguration>(
|
||||
serviceDescriptors,
|
||||
configuration,
|
||||
MassTransitConfiguration.SectionName);
|
||||
|
||||
RegisterValidatedOptions<WorkerConfiguration>(
|
||||
serviceDescriptors,
|
||||
configuration,
|
||||
WorkerConfiguration.SectionName);
|
||||
|
||||
RegisterRoutingSlipBuilders(serviceDescriptors);
|
||||
|
||||
serviceDescriptors.AddMassTransit(options =>
|
||||
{
|
||||
options.AddEntityFrameworkOutbox<Database>(outbox =>
|
||||
{
|
||||
outbox.UsePostgres();
|
||||
outbox.UseBusOutbox();
|
||||
|
||||
outbox.QueryDelay = TimeSpan.FromSeconds(1);
|
||||
outbox.DuplicateDetectionWindow = TimeSpan.FromMinutes(30);
|
||||
} );
|
||||
|
||||
options.SetKebabCaseEndpointNameFormatter();
|
||||
|
||||
RegisterConsumersAndActivities(options);
|
||||
|
||||
options.AddSagaStateMachine<TrackProcessingStateMachine, TrackProcessingState>()
|
||||
.EntityFrameworkRepository(repository =>
|
||||
{
|
||||
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||
repository.ExistingDbContext<Database>();
|
||||
repository.UsePostgres();
|
||||
} );
|
||||
|
||||
options.AddSagaStateMachine<PlayListProcessingStateMachine, PlayListProcessingState>()
|
||||
.EntityFrameworkRepository(repository =>
|
||||
{
|
||||
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||
repository.ExistingDbContext<Database>();
|
||||
repository.UsePostgres();
|
||||
} );
|
||||
|
||||
options.AddSagaStateMachine<AlbumProcessingStateMachine, AlbumProcessingState>()
|
||||
.EntityFrameworkRepository(repository =>
|
||||
{
|
||||
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||
repository.ExistingDbContext<Database>();
|
||||
repository.UsePostgres();
|
||||
} );
|
||||
|
||||
options.AddConfigureEndpointsCallback((registrationContext, _, endpointConfigurator) =>
|
||||
{
|
||||
UseStandardRetry(endpointConfigurator);
|
||||
endpointConfigurator.UseEntityFrameworkOutbox<Database>(registrationContext);
|
||||
} );
|
||||
|
||||
options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) =>
|
||||
{
|
||||
ConfigureRabbitMqHost(
|
||||
busFactoryConfigurator,
|
||||
busRegistrationContext.GetRequiredService<MassTransitConfiguration>());
|
||||
|
||||
busFactoryConfigurator.ConfigureEndpoints(busRegistrationContext);
|
||||
} );
|
||||
} );
|
||||
|
||||
return serviceDescriptors;
|
||||
}
|
||||
|
||||
static void UseStandardRetry(IReceiveEndpointConfigurator endpointConfigurator) =>
|
||||
endpointConfigurator.UseMessageRetry(retryConfigurator =>
|
||||
retryConfigurator.Exponential(
|
||||
retryLimit: 5,
|
||||
minInterval: TimeSpan.FromSeconds(1),
|
||||
maxInterval: TimeSpan.FromSeconds(30),
|
||||
intervalDelta: TimeSpan.FromSeconds(2)));
|
||||
|
||||
static void ConfigureRabbitMqHost(
|
||||
IRabbitMqBusFactoryConfigurator busFactoryConfigurator,
|
||||
MassTransitConfiguration massTransitConfiguration)
|
||||
{
|
||||
busFactoryConfigurator.Host(massTransitConfiguration.Address, options =>
|
||||
{
|
||||
options.Username(massTransitConfiguration.Username);
|
||||
options.Password(massTransitConfiguration.Password);
|
||||
} );
|
||||
}
|
||||
return serviceDescriptors;
|
||||
}
|
||||
}
|
||||
|
||||
public static IServiceCollection AddMassTransitConsumers(this IServiceCollection serviceDescriptors, IConfiguration configuration)
|
||||
{
|
||||
RegisterValidatedOptions<MassTransitConfiguration>(
|
||||
serviceDescriptors,
|
||||
configuration,
|
||||
MassTransitConfiguration.SectionName);
|
||||
|
||||
RegisterValidatedOptions<WorkerConfiguration>(
|
||||
serviceDescriptors,
|
||||
configuration,
|
||||
WorkerConfiguration.SectionName);
|
||||
|
||||
RegisterRoutingSlipBuilders(serviceDescriptors);
|
||||
|
||||
serviceDescriptors.AddMassTransit(options =>
|
||||
{
|
||||
options.AddEntityFrameworkOutbox<Database>(outbox =>
|
||||
{
|
||||
outbox.UsePostgres();
|
||||
outbox.UseBusOutbox();
|
||||
|
||||
outbox.QueryDelay = TimeSpan.FromSeconds(1);
|
||||
outbox.DuplicateDetectionWindow = TimeSpan.FromMinutes(30);
|
||||
});
|
||||
|
||||
options.SetKebabCaseEndpointNameFormatter();
|
||||
|
||||
RegisterConsumersAndActivities(options);
|
||||
|
||||
options.AddSagaStateMachine<TrackProcessingStateMachine, TrackProcessingState>()
|
||||
.EntityFrameworkRepository(repository =>
|
||||
{
|
||||
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||
repository.ExistingDbContext<Database>();
|
||||
repository.UsePostgres();
|
||||
});
|
||||
|
||||
options.AddSagaStateMachine<PlayListProcessingStateMachine, PlayListProcessingState>()
|
||||
.EntityFrameworkRepository(repository =>
|
||||
{
|
||||
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||
repository.ExistingDbContext<Database>();
|
||||
repository.UsePostgres();
|
||||
});
|
||||
|
||||
options.AddSagaStateMachine<AlbumProcessingStateMachine, AlbumProcessingState>()
|
||||
.EntityFrameworkRepository(repository =>
|
||||
{
|
||||
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||
repository.ExistingDbContext<Database>();
|
||||
repository.UsePostgres();
|
||||
});
|
||||
|
||||
options.AddConfigureEndpointsCallback((registrationContext, _, endpointConfigurator) =>
|
||||
{
|
||||
UseStandardRetry(endpointConfigurator);
|
||||
endpointConfigurator.UseEntityFrameworkOutbox<Database>(registrationContext);
|
||||
});
|
||||
|
||||
options.UsingRabbitMq((busRegistrationContext, busFactoryConfigurator) =>
|
||||
{
|
||||
ConfigureRabbitMqHost(
|
||||
busFactoryConfigurator,
|
||||
busRegistrationContext.GetRequiredService<MassTransitConfiguration>());
|
||||
|
||||
busFactoryConfigurator.ConfigureEndpoints(busRegistrationContext);
|
||||
});
|
||||
});
|
||||
|
||||
return serviceDescriptors;
|
||||
}
|
||||
|
||||
private static void UseStandardRetry(IReceiveEndpointConfigurator endpointConfigurator) =>
|
||||
endpointConfigurator.UseMessageRetry(retryConfigurator =>
|
||||
retryConfigurator.Exponential(
|
||||
retryLimit: 5,
|
||||
minInterval: TimeSpan.FromSeconds(1),
|
||||
maxInterval: TimeSpan.FromSeconds(30),
|
||||
intervalDelta: TimeSpan.FromSeconds(2)));
|
||||
|
||||
private static void ConfigureRabbitMqHost(
|
||||
IRabbitMqBusFactoryConfigurator busFactoryConfigurator,
|
||||
MassTransitConfiguration massTransitConfiguration)
|
||||
{
|
||||
busFactoryConfigurator.Host(massTransitConfiguration.Address, options =>
|
||||
{
|
||||
options.Username(massTransitConfiguration.Username);
|
||||
options.Password(massTransitConfiguration.Password);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record ConsumeUploadIntentsLog(
|
||||
Guid[] IntentIds);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record ConsumeUploadIntentsLog(
|
||||
Guid[] IntentIds);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record CopyFileInBucketLog(
|
||||
string DestinationBucket,
|
||||
string DestinationKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record CopyFileInBucketLog(
|
||||
string DestinationBucket,
|
||||
string DestinationKey);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record DownloadFileFromBucketLog(
|
||||
string Bucket,
|
||||
string Key,
|
||||
string DestinationFilePath);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record DownloadFileFromBucketLog(
|
||||
string Bucket,
|
||||
string Key,
|
||||
string DestinationFilePath);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record DownloadFileFromUrlLog(
|
||||
string SourceUrl,
|
||||
string DestinationFilePath);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record DownloadFileFromUrlLog(
|
||||
string SourceUrl,
|
||||
string DestinationFilePath);
|
||||
|
||||
+3
-4
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record GeneratePictureWorkflowPathsLog(string WorkingDirectory);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record GeneratePictureWorkflowPathsLog(string WorkingDirectory);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record ResizePictureLog(string DestinationFilePath);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record ResizePictureLog(string DestinationFilePath);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record TranscodeAudioLog(string WorkingDirectory);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record TranscodeAudioLog(string WorkingDirectory);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record TransferFilesToBucketLog(string DestinationBucket, string[] UploadedKeys);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record TransferFilesToBucketLog(string DestinationBucket, string[] UploadedKeys);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record UpdateAlbumPictureLog(
|
||||
Guid AlbumId,
|
||||
string PreviousOriginalPictureKey,
|
||||
string PreviousSmallPictureKey,
|
||||
string PreviousMediumPictureKey,
|
||||
string PreviousLargePictureKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record UpdateAlbumPictureLog(
|
||||
Guid AlbumId,
|
||||
string PreviousOriginalPictureKey,
|
||||
string PreviousSmallPictureKey,
|
||||
string PreviousMediumPictureKey,
|
||||
string PreviousLargePictureKey);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record UpdatePlayListPictureLog(
|
||||
Guid PlayListId,
|
||||
string PreviousOriginalPictureKey,
|
||||
string PreviousSmallPictureKey,
|
||||
string PreviousMediumPictureKey,
|
||||
string PreviousLargePictureKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record UpdatePlayListPictureLog(
|
||||
Guid PlayListId,
|
||||
string PreviousOriginalPictureKey,
|
||||
string PreviousSmallPictureKey,
|
||||
string PreviousMediumPictureKey,
|
||||
string PreviousLargePictureKey);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record UpdateTrackAudioLog(
|
||||
Guid TrackId,
|
||||
string? PreviousAudioFolderName,
|
||||
double PreviousDurationSeconds);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record UpdateTrackAudioLog(
|
||||
Guid TrackId,
|
||||
string? PreviousAudioFolderName,
|
||||
double PreviousDurationSeconds);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record UpdateTrackPictureLog(
|
||||
Guid TrackId,
|
||||
string? PreviousOriginalPictureKey,
|
||||
string? PreviousSmallPictureKey,
|
||||
string? PreviousMediumPictureKey,
|
||||
string? PreviousLargePictureKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record UpdateTrackPictureLog(
|
||||
Guid TrackId,
|
||||
string? PreviousOriginalPictureKey,
|
||||
string? PreviousSmallPictureKey,
|
||||
string? PreviousMediumPictureKey,
|
||||
string? PreviousLargePictureKey);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
namespace Musify.Infrastructure.MassTransit.Logs
|
||||
{
|
||||
public record UploadFileToBucketLog(string DestinationBucket, string DestinationKey);
|
||||
}
|
||||
namespace Musify.Infrastructure.MassTransit.Logs;
|
||||
|
||||
public record UploadFileToBucketLog(string DestinationBucket, string DestinationKey);
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
using MassTransit;
|
||||
using Musify.Application.Contracts;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit
|
||||
{
|
||||
public class MassTransitEventBus(IPublishEndpoint publishEndpoint)
|
||||
: IEventBus
|
||||
{
|
||||
public async Task PublishAsync<T>(T message, CancellationToken cancellationToken) where T : class
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(message, nameof(message));
|
||||
namespace Musify.Infrastructure.MassTransit;
|
||||
|
||||
await publishEndpoint.Publish(message, cancellationToken);
|
||||
}
|
||||
public class MassTransitEventBus(IPublishEndpoint publishEndpoint)
|
||||
: IEventBus
|
||||
{
|
||||
public async Task PublishAsync<T>(T message, CancellationToken cancellationToken) where T : class
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(message, nameof(message));
|
||||
|
||||
await publishEndpoint.Publish(message, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,58 @@
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip;
|
||||
|
||||
internal static class ActivityNames
|
||||
{
|
||||
internal static class ActivityNames
|
||||
{
|
||||
internal const string MarkTrackAsRemoving = "MarkTrackAsRemoving";
|
||||
internal const string MarkTrackAsFailed = "MarkTrackAsFailed";
|
||||
internal const string DeleteTrackFromDb = "DeleteTrackFromDb";
|
||||
internal const string MarkPlayListAsRemoving = "MarkPlayListAsRemoving";
|
||||
internal const string MarkPlayListAsFailed = "MarkPlayListAsFailed";
|
||||
internal const string DeletePlayListFromDb = "DeletePlayListFromDb";
|
||||
internal const string MarkAlbumAsFailed = "MarkAlbumAsFailed";
|
||||
internal const string MarkTrackAsRemoving = "MarkTrackAsRemoving";
|
||||
internal const string MarkTrackAsFailed = "MarkTrackAsFailed";
|
||||
internal const string DeleteTrackFromDb = "DeleteTrackFromDb";
|
||||
internal const string MarkPlayListAsRemoving = "MarkPlayListAsRemoving";
|
||||
internal const string MarkPlayListAsFailed = "MarkPlayListAsFailed";
|
||||
internal const string DeletePlayListFromDb = "DeletePlayListFromDb";
|
||||
internal const string MarkAlbumAsFailed = "MarkAlbumAsFailed";
|
||||
|
||||
internal const string GenerateAudioWorkflowPaths = "GenerateAudioWorkflowPaths";
|
||||
internal const string GeneratePictureWorkflowPaths = "GeneratePictureWorkflowPaths";
|
||||
internal const string GenerateAudioWorkflowPaths = "GenerateAudioWorkflowPaths";
|
||||
internal const string GeneratePictureWorkflowPaths = "GeneratePictureWorkflowPaths";
|
||||
|
||||
internal const string DownloadFile = "DownloadFile";
|
||||
internal const string DownloadThumbnail = "DownloadThumbnail";
|
||||
internal const string DownloadFile = "DownloadFile";
|
||||
internal const string DownloadThumbnail = "DownloadThumbnail";
|
||||
|
||||
internal const string TranscodeAudio = "TranscodeAudio";
|
||||
internal const string TranscodeAudio = "TranscodeAudio";
|
||||
|
||||
internal const string ResizeSmall = "ResizeSmall";
|
||||
internal const string ResizeMedium = "ResizeMedium";
|
||||
internal const string ResizeLarge = "ResizeLarge";
|
||||
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 UploadSmall = "UploadSmall";
|
||||
internal const string UploadMedium = "UploadMedium";
|
||||
internal const string UploadLarge = "UploadLarge";
|
||||
|
||||
internal const string TransferFiles = "TransferFiles";
|
||||
internal const string TransferFiles = "TransferFiles";
|
||||
|
||||
internal const string UpdateTrackPicture = "UpdateTrackPicture";
|
||||
internal const string UpdatePlayListPicture = "UpdatePlayListPicture";
|
||||
internal const string UpdateAlbumPicture = "UpdateAlbumPicture";
|
||||
internal const string UpdateTrackAudio = "UpdateTrackAudio";
|
||||
internal const string UpdateTrackPicture = "UpdateTrackPicture";
|
||||
internal const string UpdatePlayListPicture = "UpdatePlayListPicture";
|
||||
internal const string UpdateAlbumPicture = "UpdateAlbumPicture";
|
||||
internal const string UpdateTrackAudio = "UpdateTrackAudio";
|
||||
|
||||
internal const string CopyPictureToFinal = "CopyPictureToFinal";
|
||||
internal const string CopyAudioToFinal = "CopyAudioToFinal";
|
||||
internal const string CopyPictureToFinal = "CopyPictureToFinal";
|
||||
internal const string CopyAudioToFinal = "CopyAudioToFinal";
|
||||
|
||||
internal const string ConsumeUploadIntents = "ConsumeUploadIntents";
|
||||
internal const string ConsumeUploadIntents = "ConsumeUploadIntents";
|
||||
|
||||
internal const string PublishTrackProcessingEvents = "PublishTrackProcessingEvents";
|
||||
internal const string PublishPlayListPictureProcessingEvent = "PublishPlayListPictureProcessingEvent";
|
||||
internal const string PublishAlbumPictureProcessingEvent = "PublishAlbumPictureProcessingEvent";
|
||||
internal const string PublishTrackProcessingEvents = "PublishTrackProcessingEvents";
|
||||
internal const string PublishPlayListPictureProcessingEvent = "PublishPlayListPictureProcessingEvent";
|
||||
internal const string PublishAlbumPictureProcessingEvent = "PublishAlbumPictureProcessingEvent";
|
||||
|
||||
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 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";
|
||||
internal const string RemovePlayListOriginalPicture = "RemovePlayListOriginalPicture";
|
||||
internal const string RemovePlayListSmallPicture = "RemovePlayListSmallPicture";
|
||||
internal const string RemovePlayListMediumPicture = "RemovePlayListMediumPicture";
|
||||
internal const string RemovePlayListLargePicture = "RemovePlayListLargePicture";
|
||||
|
||||
internal const string RemoveAlbumOriginalPicture = "RemoveAlbumOriginalPicture";
|
||||
}
|
||||
internal const string RemoveAlbumOriginalPicture = "RemoveAlbumOriginalPicture";
|
||||
}
|
||||
|
||||
+66
-67
@@ -1,85 +1,84 @@
|
||||
using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Albums;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Activities.UploadIntents;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class AlbumPictureSourceRoutingSlipBuilder
|
||||
{
|
||||
public class AlbumPictureSourceRoutingSlipBuilder
|
||||
public RoutingSlipBuilder Build(CreateAlbumResourcesEvent message, Guid? correlationId)
|
||||
=> BuildSlip(
|
||||
message.AlbumId,
|
||||
message.PictureIntentId,
|
||||
message.Bucket,
|
||||
message.PictureSourceKey,
|
||||
message.PictureDestinationKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
public RoutingSlipBuilder Build(UpdateAlbumPictureSourceEvent message, Guid? correlationId)
|
||||
=> BuildSlip(
|
||||
message.AlbumId,
|
||||
message.PictureIntentId,
|
||||
message.Bucket,
|
||||
message.PictureSourceKey,
|
||||
message.PictureDestinationKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
private static RoutingSlipBuilder BuildSlip(
|
||||
Guid albumId,
|
||||
Guid pictureIntentId,
|
||||
string bucket,
|
||||
string pictureSourceKey,
|
||||
string pictureDestinationKey,
|
||||
ImageSize small,
|
||||
ImageSize medium,
|
||||
ImageSize large,
|
||||
Guid? correlationId)
|
||||
{
|
||||
public RoutingSlipBuilder Build(CreateAlbumResourcesEvent message, Guid? correlationId)
|
||||
=> BuildSlip(
|
||||
message.AlbumId,
|
||||
message.PictureIntentId,
|
||||
message.Bucket,
|
||||
message.PictureSourceKey,
|
||||
message.PictureDestinationKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
|
||||
public RoutingSlipBuilder Build(UpdateAlbumPictureSourceEvent message, Guid? correlationId)
|
||||
=> BuildSlip(
|
||||
message.AlbumId,
|
||||
message.PictureIntentId,
|
||||
message.Bucket,
|
||||
message.PictureSourceKey,
|
||||
message.PictureDestinationKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
static RoutingSlipBuilder BuildSlip(
|
||||
Guid albumId,
|
||||
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.AddActivity(
|
||||
ActivityNames.CopyPictureToFinal,
|
||||
EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName),
|
||||
new CopyFileInBucketArguments(
|
||||
bucket,
|
||||
pictureSourceKey,
|
||||
bucket,
|
||||
pictureDestinationKey));
|
||||
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.ConsumeUploadIntents,
|
||||
EndpointHelper.BuildExecuteActivityUri(ConsumeUploadIntentsActivity.ExecuteEndpointName),
|
||||
new ConsumeUploadIntentsArguments([pictureIntentId]));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.CopyPictureToFinal,
|
||||
EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName),
|
||||
new CopyFileInBucketArguments(
|
||||
bucket,
|
||||
pictureSourceKey,
|
||||
bucket,
|
||||
pictureDestinationKey));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.PublishAlbumPictureProcessingEvent,
|
||||
EndpointHelper.BuildExecuteActivityUri(PublishAlbumPictureProcessingEventActivity.ExecuteEndpointName),
|
||||
new PublishAlbumPictureProcessingEventArguments(
|
||||
albumId,
|
||||
bucket,
|
||||
pictureDestinationKey,
|
||||
small,
|
||||
medium,
|
||||
large));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.ConsumeUploadIntents,
|
||||
EndpointHelper.BuildExecuteActivityUri(ConsumeUploadIntentsActivity.ExecuteEndpointName),
|
||||
new ConsumeUploadIntentsArguments([pictureIntentId]));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.PublishAlbumPictureProcessingEvent,
|
||||
EndpointHelper.BuildExecuteActivityUri(PublishAlbumPictureProcessingEventActivity.ExecuteEndpointName),
|
||||
new PublishAlbumPictureProcessingEventArguments(
|
||||
albumId,
|
||||
bucket,
|
||||
pictureDestinationKey,
|
||||
small,
|
||||
medium,
|
||||
large));
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+50
-51
@@ -7,66 +7,65 @@ using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class AudioWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
|
||||
{
|
||||
public class AudioWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
|
||||
public RoutingSlipBuilder Build(UpdateTrackAudioEvent message, Guid? correlationId)
|
||||
{
|
||||
public RoutingSlipBuilder Build(UpdateTrackAudioEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
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.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.GenerateAudioWorkflowPaths,
|
||||
EndpointHelper.BuildExecuteActivityUri(GenerateAudioWorkflowPathsActivity.ExecuteEndpointName),
|
||||
new GenerateAudioWorkflowPathsArguments(
|
||||
message.TrackId,
|
||||
workerConfiguration.Routes.TemporaryFilesDirectory,
|
||||
message.SourceKey));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.GenerateAudioWorkflowPaths,
|
||||
EndpointHelper.BuildExecuteActivityUri(GenerateAudioWorkflowPathsActivity.ExecuteEndpointName),
|
||||
new GenerateAudioWorkflowPathsArguments(
|
||||
message.TrackId,
|
||||
workerConfiguration.Routes.TemporaryFilesDirectory,
|
||||
message.SourceKey));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DownloadFile,
|
||||
EndpointHelper.BuildExecuteActivityUri(DownloadFileFromBucketActivity.ExecuteEndpointName),
|
||||
new DownloadFileFromBucketArguments(
|
||||
message.SourceBucket,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Audio.SourceFilePath));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DownloadFile,
|
||||
EndpointHelper.BuildExecuteActivityUri(DownloadFileFromBucketActivity.ExecuteEndpointName),
|
||||
new DownloadFileFromBucketArguments(
|
||||
message.SourceBucket,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Audio.SourceFilePath));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.TranscodeAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(TranscodeAudioActivity.ExecuteEndpointName),
|
||||
new TranscodeAudioArguments(
|
||||
message.TrackId,
|
||||
RoutingSlipVariableNames.Audio.SourceFilePath,
|
||||
RoutingSlipVariableNames.Workflow.TemporalDirectory));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.TranscodeAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(TranscodeAudioActivity.ExecuteEndpointName),
|
||||
new TranscodeAudioArguments(
|
||||
message.TrackId,
|
||||
RoutingSlipVariableNames.Audio.SourceFilePath,
|
||||
RoutingSlipVariableNames.Workflow.TemporalDirectory));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.TransferFiles,
|
||||
EndpointHelper.BuildExecuteActivityUri(TransferFilesToBucketActivity.ExecuteEndpointName),
|
||||
new TransferFilesToBucketArguments(
|
||||
message.DestinationBucket,
|
||||
RoutingSlipVariableNames.Audio.TranscodedDirectory,
|
||||
message.DestinationFolderKey));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.TransferFiles,
|
||||
EndpointHelper.BuildExecuteActivityUri(TransferFilesToBucketActivity.ExecuteEndpointName),
|
||||
new TransferFilesToBucketArguments(
|
||||
message.DestinationBucket,
|
||||
RoutingSlipVariableNames.Audio.TranscodedDirectory,
|
||||
message.DestinationFolderKey));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdateTrackAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdateTrackAudioActivity.ExecuteEndpointName),
|
||||
new UpdateTrackAudioArguments(
|
||||
message.TrackId,
|
||||
message.DestinationFolderKey,
|
||||
RoutingSlipVariableNames.Audio.DurationSeconds));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdateTrackAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdateTrackAudioActivity.ExecuteEndpointName),
|
||||
new UpdateTrackAudioArguments(
|
||||
message.TrackId,
|
||||
message.DestinationFolderKey,
|
||||
RoutingSlipVariableNames.Audio.DurationSeconds));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackAudio);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackAudio);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+43
-44
@@ -7,57 +7,56 @@ using Musify.Infrastructure.MassTransit.Activities.UploadIntents;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class CreateTrackRoutingSlipBuilder
|
||||
{
|
||||
public class CreateTrackRoutingSlipBuilder
|
||||
public RoutingSlipBuilder Build(CreateTrackResourcesEvent message, Guid? correlationId)
|
||||
{
|
||||
public RoutingSlipBuilder Build(CreateTrackResourcesEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
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.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.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.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.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));
|
||||
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;
|
||||
}
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+73
-74
@@ -2,93 +2,92 @@ using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Musify.Application.Configuration;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Consumers;
|
||||
using Musify.Application.Contracts;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class DeletePlayListRoutingSlipBuilder(
|
||||
IDatabase database,
|
||||
PlayListConfiguration playListConfiguration,
|
||||
ApplicationStorageConfiguration storageConfiguration)
|
||||
{
|
||||
public class DeletePlayListRoutingSlipBuilder(
|
||||
IDatabase database,
|
||||
PlayListConfiguration playListConfiguration,
|
||||
ApplicationStorageConfiguration storageConfiguration)
|
||||
public async Task<RoutingSlipBuilder> BuildAsync(
|
||||
Guid playListId,
|
||||
long userId,
|
||||
Guid? correlationId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
public async Task<RoutingSlipBuilder> BuildAsync(
|
||||
Guid playListId,
|
||||
long userId,
|
||||
Guid? correlationId,
|
||||
CancellationToken cancellationToken)
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
var playList = await database.PlayLists
|
||||
.AsNoTracking()
|
||||
.SingleOrDefaultAsync(p => p.Id == playListId, cancellationToken);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.MarkPlayListAsRemoving,
|
||||
EndpointHelper.BuildExecuteActivityUri(MarkPlayListAsRemovingActivity.ExecuteEndpointName),
|
||||
new MarkPlayListAsRemovingArguments(playListId));
|
||||
|
||||
if (playList?.Pictures != null)
|
||||
{
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
var bucket = storageConfiguration.Bucket;
|
||||
var routes = playListConfiguration.Routes;
|
||||
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
var playList = await database.PlayLists
|
||||
.AsNoTracking()
|
||||
.SingleOrDefaultAsync(p => p.Id == playListId, cancellationToken);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.MarkPlayListAsRemoving,
|
||||
EndpointHelper.BuildExecuteActivityUri(MarkPlayListAsRemovingActivity.ExecuteEndpointName),
|
||||
new MarkPlayListAsRemovingArguments(playListId));
|
||||
|
||||
if (playList?.Pictures != null)
|
||||
if (playList.Pictures.OriginalName is { } originalName)
|
||||
{
|
||||
var bucket = storageConfiguration.Bucket;
|
||||
var routes = playListConfiguration.Routes;
|
||||
|
||||
if (playList.Pictures.OriginalName is { } originalName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListOriginalPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildOriginalPicturePath(userId, originalName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.SmallName is { } smallName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListSmallPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildSmallPicturePath(smallName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.MediumName is { } mediumName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListMediumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildMediumPicturePath(mediumName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.LargeName is { } largeName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListLargePicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildLargePicturePath(largeName)));
|
||||
}
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListOriginalPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildOriginalPicturePath(userId, originalName)));
|
||||
}
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DeletePlayListFromDb,
|
||||
EndpointHelper.BuildExecuteActivityUri(DeletePlayListFromDbActivity.ExecuteEndpointName),
|
||||
new DeletePlayListFromDbArguments(playListId));
|
||||
if (playList.Pictures.SmallName is { } smallName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListSmallPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildSmallPicturePath(smallName)));
|
||||
}
|
||||
|
||||
return routingSlipBuilder;
|
||||
if (playList.Pictures.MediumName is { } mediumName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListMediumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildMediumPicturePath(mediumName)));
|
||||
}
|
||||
|
||||
if (playList.Pictures.LargeName is { } largeName)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemovePlayListLargePicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
routes.BuildLargePicturePath(largeName)));
|
||||
}
|
||||
}
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DeletePlayListFromDb,
|
||||
EndpointHelper.BuildExecuteActivityUri(DeletePlayListFromDbActivity.ExecuteEndpointName),
|
||||
new DeletePlayListFromDbArguments(playListId));
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+86
-87
@@ -2,106 +2,105 @@ using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Musify.Application.Configuration;
|
||||
using Musify.Application.Contracts;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Tracks;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Consumers;
|
||||
using Musify.Application.Contracts;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class DeleteTrackRoutingSlipBuilder(
|
||||
IDatabase database,
|
||||
TrackConfiguration trackConfiguration,
|
||||
ApplicationStorageConfiguration storageConfiguration)
|
||||
{
|
||||
public class DeleteTrackRoutingSlipBuilder(
|
||||
IDatabase database,
|
||||
TrackConfiguration trackConfiguration,
|
||||
ApplicationStorageConfiguration storageConfiguration)
|
||||
public async Task<RoutingSlipBuilder> BuildAsync(
|
||||
Guid trackId,
|
||||
long userId,
|
||||
Guid? correlationId,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
public async Task<RoutingSlipBuilder> BuildAsync(
|
||||
Guid trackId,
|
||||
long userId,
|
||||
Guid? correlationId,
|
||||
CancellationToken cancellationToken)
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
var track = await database.Tracks
|
||||
.AsNoTracking()
|
||||
.SingleOrDefaultAsync(t => t.Id == trackId, cancellationToken);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.MarkTrackAsRemoving,
|
||||
EndpointHelper.BuildExecuteActivityUri(MarkTrackAsRemovingActivity.ExecuteEndpointName),
|
||||
new MarkTrackAsRemovingArguments(trackId));
|
||||
|
||||
if (track != null)
|
||||
{
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
var bucket = storageConfiguration.Bucket;
|
||||
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
var track = await database.Tracks
|
||||
.AsNoTracking()
|
||||
.SingleOrDefaultAsync(t => t.Id == trackId, cancellationToken);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.MarkTrackAsRemoving,
|
||||
EndpointHelper.BuildExecuteActivityUri(MarkTrackAsRemovingActivity.ExecuteEndpointName),
|
||||
new MarkTrackAsRemovingArguments(trackId));
|
||||
|
||||
if (track != null)
|
||||
if (!string.IsNullOrEmpty(track.Pictures.OriginalName))
|
||||
{
|
||||
var bucket = storageConfiguration.Bucket;
|
||||
|
||||
if (!string.IsNullOrEmpty(track.Pictures.OriginalName))
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackOriginalPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildOriginalPicturePath(userId, track.Pictures.OriginalName)));
|
||||
}
|
||||
|
||||
if (track.Pictures.IsProcessed)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackSmallPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildSmallPicturePath(track.Pictures.SmallName)));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackMediumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildMediumPicturePath(track.Pictures.MediumName)));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackLargePicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildLargePicturePath(track.Pictures.LargeName)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(track.Audio.OriginalName))
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackOriginalAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildOriginalAudioPath(userId, track.Audio.OriginalName)));
|
||||
}
|
||||
|
||||
if (track.Audio.IsProcessed)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackProcessedAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildProcessedAudioPath(track.Audio.FolderName)));
|
||||
}
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackOriginalPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildOriginalPicturePath(userId, track.Pictures.OriginalName)));
|
||||
}
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DeleteTrackFromDb,
|
||||
EndpointHelper.BuildExecuteActivityUri(DeleteTrackFromDbActivity.ExecuteEndpointName),
|
||||
new DeleteTrackFromDbArguments(trackId));
|
||||
if (track.Pictures.IsProcessed)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackSmallPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildSmallPicturePath(track.Pictures.SmallName)));
|
||||
|
||||
return routingSlipBuilder;
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackMediumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildMediumPicturePath(track.Pictures.MediumName)));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackLargePicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildLargePicturePath(track.Pictures.LargeName)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(track.Audio.OriginalName))
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackOriginalAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildOriginalAudioPath(userId, track.Audio.OriginalName)));
|
||||
}
|
||||
|
||||
if (track.Audio.IsProcessed)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.RemoveTrackProcessedAudio,
|
||||
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
|
||||
new RemoveFileFromBucketArguments(
|
||||
bucket,
|
||||
trackConfiguration.Routes.BuildProcessedAudioPath(track.Audio.FolderName)));
|
||||
}
|
||||
}
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DeleteTrackFromDb,
|
||||
EndpointHelper.BuildExecuteActivityUri(DeleteTrackFromDbActivity.ExecuteEndpointName),
|
||||
new DeleteTrackFromDbArguments(trackId));
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+168
-169
@@ -1,185 +1,184 @@
|
||||
using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Infrastructure.Configuration;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||
using Musify.Infrastructure.MassTransit.Activities.Pictures;
|
||||
using Musify.Infrastructure.MassTransit.Arguments;
|
||||
using Musify.Infrastructure.MassTransit.Consumers;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class PictureWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
|
||||
{
|
||||
public class PictureWorkflowRoutingSlipBuilder(WorkerConfiguration workerConfiguration)
|
||||
public RoutingSlipBuilder Build(UpdateTrackPictureEvent message, Guid? correlationId)
|
||||
{
|
||||
public RoutingSlipBuilder Build(UpdateTrackPictureEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = BuildPictureWorkflow(
|
||||
message.Bucket,
|
||||
var routingSlipBuilder = BuildPictureWorkflow(
|
||||
message.Bucket,
|
||||
message.SourceKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdateTrackPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdateTrackPictureActivity.ExecuteEndpointName),
|
||||
new UpdateTrackPictureArguments(
|
||||
message.TrackId,
|
||||
message.SourceKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdateTrackPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdateTrackPictureActivity.ExecuteEndpointName),
|
||||
new UpdateTrackPictureArguments(
|
||||
message.TrackId,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackPicture);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
public RoutingSlipBuilder Build(UpdatePlayListPictureEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = BuildPictureWorkflow(
|
||||
message.Bucket,
|
||||
message.SourceKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdatePlayListPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdatePlayListPictureActivity.ExecuteEndpointName),
|
||||
new UpdatePlayListPictureArguments(
|
||||
message.PlayListId,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.PlayListId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.PlayListPicture);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
public RoutingSlipBuilder Build(UpdateAlbumPictureEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = BuildPictureWorkflow(
|
||||
message.Bucket,
|
||||
message.SourceKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdateAlbumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdateAlbumPictureActivity.ExecuteEndpointName),
|
||||
new UpdateAlbumPictureArguments(
|
||||
message.AlbumId,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.AlbumId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.AlbumPicture);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
RoutingSlipBuilder BuildPictureWorkflow(
|
||||
string bucket,
|
||||
string sourceKey,
|
||||
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.GeneratePictureWorkflowPaths,
|
||||
EndpointHelper.BuildExecuteActivityUri(GeneratePictureWorkflowPathsActivity.ExecuteEndpointName),
|
||||
new GeneratePictureWorkflowPathsArguments(
|
||||
workerConfiguration.Routes.TemporaryFilesDirectory,
|
||||
sourceKey));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DownloadFile,
|
||||
EndpointHelper.BuildExecuteActivityUri(DownloadFileFromBucketActivity.ExecuteEndpointName),
|
||||
new DownloadFileFromBucketArguments(
|
||||
bucket,
|
||||
sourceKey,
|
||||
RoutingSlipVariableNames.Picture.OriginalFilePath));
|
||||
|
||||
AddResizeActivity(
|
||||
routingSlipBuilder,
|
||||
ActivityNames.ResizeSmall,
|
||||
ActivityNames.UploadSmall,
|
||||
bucket,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
small);
|
||||
|
||||
AddResizeActivity(
|
||||
routingSlipBuilder,
|
||||
ActivityNames.ResizeMedium,
|
||||
ActivityNames.UploadMedium,
|
||||
bucket,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
medium);
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||
|
||||
AddResizeActivity(
|
||||
routingSlipBuilder,
|
||||
ActivityNames.ResizeLarge,
|
||||
ActivityNames.UploadLarge,
|
||||
bucket,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath,
|
||||
large);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackPicture);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
static void AddResizeActivity(
|
||||
RoutingSlipBuilder routingSlipBuilder,
|
||||
string resizeActivityName,
|
||||
string uploadActivityName,
|
||||
string bucketName,
|
||||
string destinationFilePathVariableName,
|
||||
ImageSize imageSize)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
resizeActivityName,
|
||||
EndpointHelper.BuildExecuteActivityUri(ResizePictureActivity.ExecuteEndpointName),
|
||||
new ResizePictureLocalArguments(
|
||||
RoutingSlipVariableNames.Picture.OriginalFilePath,
|
||||
destinationFilePathVariableName,
|
||||
imageSize.Width,
|
||||
imageSize.Height));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
uploadActivityName,
|
||||
EndpointHelper.BuildExecuteActivityUri(UploadFileToBucketActivity.ExecuteEndpointName),
|
||||
new UploadFileToBucketArguments(
|
||||
destinationFilePathVariableName,
|
||||
bucketName,
|
||||
imageSize.SavePath));
|
||||
}
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
public RoutingSlipBuilder Build(UpdatePlayListPictureEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = BuildPictureWorkflow(
|
||||
message.Bucket,
|
||||
message.SourceKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdatePlayListPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdatePlayListPictureActivity.ExecuteEndpointName),
|
||||
new UpdatePlayListPictureArguments(
|
||||
message.PlayListId,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.PlayListId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.PlayListPicture);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
public RoutingSlipBuilder Build(UpdateAlbumPictureEvent message, Guid? correlationId)
|
||||
{
|
||||
var routingSlipBuilder = BuildPictureWorkflow(
|
||||
message.Bucket,
|
||||
message.SourceKey,
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.UpdateAlbumPicture,
|
||||
EndpointHelper.BuildExecuteActivityUri(UpdateAlbumPictureActivity.ExecuteEndpointName),
|
||||
new UpdateAlbumPictureArguments(
|
||||
message.AlbumId,
|
||||
message.SourceKey,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.AlbumId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.AlbumPicture);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
private RoutingSlipBuilder BuildPictureWorkflow(
|
||||
string bucket,
|
||||
string sourceKey,
|
||||
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.GeneratePictureWorkflowPaths,
|
||||
EndpointHelper.BuildExecuteActivityUri(GeneratePictureWorkflowPathsActivity.ExecuteEndpointName),
|
||||
new GeneratePictureWorkflowPathsArguments(
|
||||
workerConfiguration.Routes.TemporaryFilesDirectory,
|
||||
sourceKey));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.DownloadFile,
|
||||
EndpointHelper.BuildExecuteActivityUri(DownloadFileFromBucketActivity.ExecuteEndpointName),
|
||||
new DownloadFileFromBucketArguments(
|
||||
bucket,
|
||||
sourceKey,
|
||||
RoutingSlipVariableNames.Picture.OriginalFilePath));
|
||||
|
||||
AddResizeActivity(
|
||||
routingSlipBuilder,
|
||||
ActivityNames.ResizeSmall,
|
||||
ActivityNames.UploadSmall,
|
||||
bucket,
|
||||
RoutingSlipVariableNames.Picture.SmallResizedFilePath,
|
||||
small);
|
||||
|
||||
AddResizeActivity(
|
||||
routingSlipBuilder,
|
||||
ActivityNames.ResizeMedium,
|
||||
ActivityNames.UploadMedium,
|
||||
bucket,
|
||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||
medium);
|
||||
|
||||
AddResizeActivity(
|
||||
routingSlipBuilder,
|
||||
ActivityNames.ResizeLarge,
|
||||
ActivityNames.UploadLarge,
|
||||
bucket,
|
||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath,
|
||||
large);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
|
||||
private static void AddResizeActivity(
|
||||
RoutingSlipBuilder routingSlipBuilder,
|
||||
string resizeActivityName,
|
||||
string uploadActivityName,
|
||||
string bucketName,
|
||||
string destinationFilePathVariableName,
|
||||
ImageSize imageSize)
|
||||
{
|
||||
routingSlipBuilder.AddActivity(
|
||||
resizeActivityName,
|
||||
EndpointHelper.BuildExecuteActivityUri(ResizePictureActivity.ExecuteEndpointName),
|
||||
new ResizePictureLocalArguments(
|
||||
RoutingSlipVariableNames.Picture.OriginalFilePath,
|
||||
destinationFilePathVariableName,
|
||||
imageSize.Width,
|
||||
imageSize.Height));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
uploadActivityName,
|
||||
EndpointHelper.BuildExecuteActivityUri(UploadFileToBucketActivity.ExecuteEndpointName),
|
||||
new UploadFileToBucketArguments(
|
||||
destinationFilePathVariableName,
|
||||
bucketName,
|
||||
imageSize.SavePath));
|
||||
}
|
||||
}
|
||||
|
||||
+66
-67
@@ -1,85 +1,84 @@
|
||||
using MassTransit;
|
||||
using MassTransit.Courier.Contracts;
|
||||
using Musify.Application.Shared;
|
||||
using Musify.Application.Events;
|
||||
using Musify.Application.Shared;
|
||||
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
|
||||
namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders;
|
||||
|
||||
public class PlayListPictureSourceRoutingSlipBuilder
|
||||
{
|
||||
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);
|
||||
|
||||
private static RoutingSlipBuilder BuildSlip(
|
||||
Guid playListId,
|
||||
Guid pictureIntentId,
|
||||
string bucket,
|
||||
string pictureSourceKey,
|
||||
string pictureDestinationKey,
|
||||
ImageSize small,
|
||||
ImageSize medium,
|
||||
ImageSize large,
|
||||
Guid? correlationId)
|
||||
{
|
||||
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);
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
|
||||
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);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
|
||||
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.AddActivity(
|
||||
ActivityNames.CopyPictureToFinal,
|
||||
EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName),
|
||||
new CopyFileInBucketArguments(
|
||||
bucket,
|
||||
pictureSourceKey,
|
||||
bucket,
|
||||
pictureDestinationKey));
|
||||
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(RoutingSlipCleanUpConsumer.QueueName),
|
||||
RoutingSlipEvents.Completed | RoutingSlipEvents.Faulted);
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.ConsumeUploadIntents,
|
||||
EndpointHelper.BuildExecuteActivityUri(ConsumeUploadIntentsActivity.ExecuteEndpointName),
|
||||
new ConsumeUploadIntentsArguments([pictureIntentId]));
|
||||
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.CopyPictureToFinal,
|
||||
EndpointHelper.BuildExecuteActivityUri(CopyFileInBucketActivity.ExecuteEndpointName),
|
||||
new CopyFileInBucketArguments(
|
||||
bucket,
|
||||
pictureSourceKey,
|
||||
bucket,
|
||||
pictureDestinationKey));
|
||||
routingSlipBuilder.AddActivity(
|
||||
ActivityNames.PublishPlayListPictureProcessingEvent,
|
||||
EndpointHelper.BuildExecuteActivityUri(PublishPlayListPictureProcessingEventActivity.ExecuteEndpointName),
|
||||
new PublishPlayListPictureProcessingEventArguments(
|
||||
playListId,
|
||||
bucket,
|
||||
pictureDestinationKey,
|
||||
small,
|
||||
medium,
|
||||
large));
|
||||
|
||||
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;
|
||||
}
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+28
-29
@@ -1,36 +1,35 @@
|
||||
namespace Musify.Infrastructure.MassTransit
|
||||
namespace Musify.Infrastructure.MassTransit;
|
||||
|
||||
internal static class RoutingSlipVariableNames
|
||||
{
|
||||
internal static class RoutingSlipVariableNames
|
||||
internal static class Workflow
|
||||
{
|
||||
internal static class Workflow
|
||||
{
|
||||
internal const string TemporalDirectory = "Workflow.TemporalDirectory";
|
||||
internal const string CorrelationId = "Workflow.CorrelationId";
|
||||
internal const string SubjectId = "Workflow.SubjectId";
|
||||
internal const string ProcessKind = "Workflow.ProcessKind";
|
||||
}
|
||||
internal const string TemporalDirectory = "Workflow.TemporalDirectory";
|
||||
internal const string CorrelationId = "Workflow.CorrelationId";
|
||||
internal const string SubjectId = "Workflow.SubjectId";
|
||||
internal const string ProcessKind = "Workflow.ProcessKind";
|
||||
}
|
||||
|
||||
internal static class ProcessKinds
|
||||
{
|
||||
internal const string TrackPicture = "TrackPicture";
|
||||
internal const string TrackAudio = "TrackAudio";
|
||||
internal const string PlayListPicture = "PlayListPicture";
|
||||
internal const string AlbumPicture = "AlbumPicture";
|
||||
}
|
||||
internal static class ProcessKinds
|
||||
{
|
||||
internal const string TrackPicture = "TrackPicture";
|
||||
internal const string TrackAudio = "TrackAudio";
|
||||
internal const string PlayListPicture = "PlayListPicture";
|
||||
internal const string AlbumPicture = "AlbumPicture";
|
||||
}
|
||||
|
||||
internal static class Audio
|
||||
{
|
||||
internal const string SourceFilePath = "Audio.SourceFilePath";
|
||||
internal const string TranscodedDirectory = "Audio.TranscodedDirectory";
|
||||
internal const string DurationSeconds = "Audio.DurationSeconds";
|
||||
}
|
||||
internal static class Audio
|
||||
{
|
||||
internal const string SourceFilePath = "Audio.SourceFilePath";
|
||||
internal const string TranscodedDirectory = "Audio.TranscodedDirectory";
|
||||
internal const string DurationSeconds = "Audio.DurationSeconds";
|
||||
}
|
||||
|
||||
internal static class Picture
|
||||
{
|
||||
internal const string OriginalFilePath = "Picture.OriginalFilePath";
|
||||
internal const string SmallResizedFilePath = "Picture.SmallResizedFilePath";
|
||||
internal const string MediumResizedFilePath = "Picture.MediumResizedFilePath";
|
||||
internal const string LargeResizedFilePath = "Picture.LargeResizedFilePath";
|
||||
}
|
||||
internal static class Picture
|
||||
{
|
||||
internal const string OriginalFilePath = "Picture.OriginalFilePath";
|
||||
internal const string SmallResizedFilePath = "Picture.SmallResizedFilePath";
|
||||
internal const string MediumResizedFilePath = "Picture.MediumResizedFilePath";
|
||||
internal const string LargeResizedFilePath = "Picture.LargeResizedFilePath";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
using MassTransit;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas;
|
||||
|
||||
public class AlbumProcessingState : SagaStateMachineInstance
|
||||
{
|
||||
public class AlbumProcessingState : SagaStateMachineInstance
|
||||
{
|
||||
public Guid CorrelationId { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
|
||||
public string CurrentState { get; set; } = null!;
|
||||
public string CurrentState { get; set; } = null!;
|
||||
|
||||
public string? Bucket { get; set; }
|
||||
public string? Bucket { get; set; }
|
||||
|
||||
public string? PictureKey { get; set; }
|
||||
public string? PictureKey { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
|
||||
+38
-39
@@ -1,51 +1,50 @@
|
||||
using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas;
|
||||
|
||||
public sealed class AlbumProcessingStateMachine : MassTransitStateMachine<AlbumProcessingState>
|
||||
{
|
||||
public sealed class AlbumProcessingStateMachine : MassTransitStateMachine<AlbumProcessingState>
|
||||
public State Processing { get; private set; } = null!;
|
||||
public State Failed { get; private set; } = null!;
|
||||
|
||||
public Event<CreateAlbumResourcesEvent> ProcessingStarted { get; private set; } = null!;
|
||||
public Event<AlbumPictureProcessed> PictureProcessed { get; private set; } = null!;
|
||||
public Event<AlbumPictureProcessingFailed> PictureFailed { get; private set; } = null!;
|
||||
|
||||
public AlbumProcessingStateMachine()
|
||||
{
|
||||
public State Processing { get; private set; } = null!;
|
||||
public State Failed { get; private set; } = null!;
|
||||
InstanceState(state => state.CurrentState);
|
||||
|
||||
public Event<CreateAlbumResourcesEvent> ProcessingStarted { get; private set; } = null!;
|
||||
public Event<AlbumPictureProcessed> PictureProcessed { get; private set; } = null!;
|
||||
public Event<AlbumPictureProcessingFailed> PictureFailed { get; private set; } = null!;
|
||||
Event(() => ProcessingStarted, config => config.CorrelateById(context => context.Message.AlbumId));
|
||||
Event(() => PictureProcessed, config => config.CorrelateById(context => context.Message.AlbumId));
|
||||
Event(() => PictureFailed, config => config.CorrelateById(context => context.Message.AlbumId));
|
||||
|
||||
public AlbumProcessingStateMachine()
|
||||
{
|
||||
InstanceState(state => state.CurrentState);
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.CreatedAt = DateTime.UtcNow;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
context.Saga.Bucket = context.Message.Bucket;
|
||||
context.Saga.PictureKey = context.Message.PictureDestinationKey;
|
||||
})
|
||||
.TransitionTo(Processing));
|
||||
|
||||
Event(() => ProcessingStarted, config => config.CorrelateById(context => context.Message.AlbumId));
|
||||
Event(() => PictureProcessed, config => config.CorrelateById(context => context.Message.AlbumId));
|
||||
Event(() => PictureFailed, config => config.CorrelateById(context => context.Message.AlbumId));
|
||||
During(Processing,
|
||||
When(PictureProcessed).Finalize(),
|
||||
When(PictureFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new AlbumProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey)));
|
||||
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.CreatedAt = DateTime.UtcNow;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
context.Saga.Bucket = context.Message.Bucket;
|
||||
context.Saga.PictureKey = context.Message.PictureDestinationKey;
|
||||
} )
|
||||
.TransitionTo(Processing));
|
||||
During(Failed,
|
||||
Ignore(PictureProcessed),
|
||||
Ignore(PictureFailed));
|
||||
|
||||
During(Processing,
|
||||
When(PictureProcessed).Finalize(),
|
||||
When(PictureFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new AlbumProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey)));
|
||||
|
||||
During(Failed,
|
||||
Ignore(PictureProcessed),
|
||||
Ignore(PictureFailed));
|
||||
|
||||
SetCompletedWhenFinalized();
|
||||
}
|
||||
SetCompletedWhenFinalized();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
using MassTransit;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas;
|
||||
|
||||
public class PlayListProcessingState : SagaStateMachineInstance
|
||||
{
|
||||
public class PlayListProcessingState : SagaStateMachineInstance
|
||||
{
|
||||
public Guid CorrelationId { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
|
||||
public string CurrentState { get; set; } = null!;
|
||||
public string CurrentState { get; set; } = null!;
|
||||
|
||||
public string? Bucket { get; set; }
|
||||
public string? Bucket { get; set; }
|
||||
|
||||
public string? PictureKey { get; set; }
|
||||
public string? PictureKey { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
|
||||
+38
-39
@@ -1,51 +1,50 @@
|
||||
using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas;
|
||||
|
||||
public sealed class PlayListProcessingStateMachine : MassTransitStateMachine<PlayListProcessingState>
|
||||
{
|
||||
public sealed class PlayListProcessingStateMachine : MassTransitStateMachine<PlayListProcessingState>
|
||||
public State Processing { get; private set; } = null!;
|
||||
public State Failed { get; private set; } = null!;
|
||||
|
||||
public Event<CreatePlayListResourcesEvent> ProcessingStarted { get; private set; } = null!;
|
||||
public Event<PlayListPictureProcessed> PictureProcessed { get; private set; } = null!;
|
||||
public Event<PlayListPictureProcessingFailed> PictureFailed { get; private set; } = null!;
|
||||
|
||||
public PlayListProcessingStateMachine()
|
||||
{
|
||||
public State Processing { get; private set; } = null!;
|
||||
public State Failed { get; private set; } = null!;
|
||||
InstanceState(state => state.CurrentState);
|
||||
|
||||
public Event<CreatePlayListResourcesEvent> ProcessingStarted { get; private set; } = null!;
|
||||
public Event<PlayListPictureProcessed> PictureProcessed { get; private set; } = null!;
|
||||
public Event<PlayListPictureProcessingFailed> PictureFailed { get; private set; } = null!;
|
||||
Event(() => ProcessingStarted, config => config.CorrelateById(context => context.Message.PlayListId));
|
||||
Event(() => PictureProcessed, config => config.CorrelateById(context => context.Message.PlayListId));
|
||||
Event(() => PictureFailed, config => config.CorrelateById(context => context.Message.PlayListId));
|
||||
|
||||
public PlayListProcessingStateMachine()
|
||||
{
|
||||
InstanceState(state => state.CurrentState);
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.CreatedAt = DateTime.UtcNow;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
context.Saga.Bucket = context.Message.Bucket;
|
||||
context.Saga.PictureKey = context.Message.PictureDestinationKey;
|
||||
})
|
||||
.TransitionTo(Processing));
|
||||
|
||||
Event(() => ProcessingStarted, config => config.CorrelateById(context => context.Message.PlayListId));
|
||||
Event(() => PictureProcessed, config => config.CorrelateById(context => context.Message.PlayListId));
|
||||
Event(() => PictureFailed, config => config.CorrelateById(context => context.Message.PlayListId));
|
||||
During(Processing,
|
||||
When(PictureProcessed).Finalize(),
|
||||
When(PictureFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new PlayListProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey)));
|
||||
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.CreatedAt = DateTime.UtcNow;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
context.Saga.Bucket = context.Message.Bucket;
|
||||
context.Saga.PictureKey = context.Message.PictureDestinationKey;
|
||||
} )
|
||||
.TransitionTo(Processing));
|
||||
During(Failed,
|
||||
Ignore(PictureProcessed),
|
||||
Ignore(PictureFailed));
|
||||
|
||||
During(Processing,
|
||||
When(PictureProcessed).Finalize(),
|
||||
When(PictureFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new PlayListProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey)));
|
||||
|
||||
During(Failed,
|
||||
Ignore(PictureProcessed),
|
||||
Ignore(PictureFailed));
|
||||
|
||||
SetCompletedWhenFinalized();
|
||||
}
|
||||
SetCompletedWhenFinalized();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
using MassTransit;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas;
|
||||
|
||||
public class TrackProcessingState : SagaStateMachineInstance
|
||||
{
|
||||
public class TrackProcessingState : SagaStateMachineInstance
|
||||
{
|
||||
public Guid CorrelationId { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
|
||||
public string CurrentState { get; set; } = null!;
|
||||
public string CurrentState { get; set; } = null!;
|
||||
|
||||
public bool PictureProcessed { get; set; }
|
||||
public bool PictureProcessed { get; set; }
|
||||
|
||||
public bool AudioProcessed { get; set; }
|
||||
public bool AudioProcessed { get; set; }
|
||||
|
||||
public string? Bucket { get; set; }
|
||||
public string? Bucket { get; set; }
|
||||
|
||||
public string? PictureKey { get; set; }
|
||||
public string? PictureKey { get; set; }
|
||||
|
||||
public string? AudioKey { get; set; }
|
||||
public string? AudioKey { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
|
||||
+67
-68
@@ -1,80 +1,79 @@
|
||||
using MassTransit;
|
||||
using Musify.Application.Events;
|
||||
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||
namespace Musify.Infrastructure.MassTransit.Sagas;
|
||||
|
||||
public sealed class TrackProcessingStateMachine : MassTransitStateMachine<TrackProcessingState>
|
||||
{
|
||||
public sealed class TrackProcessingStateMachine : MassTransitStateMachine<TrackProcessingState>
|
||||
public State Processing { get; private set; } = null!;
|
||||
public State Failed { get; private set; } = null!;
|
||||
|
||||
public Event<CreateTrackResourcesEvent> ProcessingStarted { get; private set; } = null!;
|
||||
public Event<TrackPictureProcessed> PictureProcessed { get; private set; } = null!;
|
||||
public Event<TrackAudioProcessed> AudioProcessed { get; private set; } = null!;
|
||||
public Event<TrackPictureProcessingFailed> PictureFailed { get; private set; } = null!;
|
||||
public Event<TrackAudioProcessingFailed> AudioFailed { get; private set; } = null!;
|
||||
|
||||
public TrackProcessingStateMachine()
|
||||
{
|
||||
public State Processing { get; private set; } = null!;
|
||||
public State Failed { get; private set; } = null!;
|
||||
InstanceState(state => state.CurrentState);
|
||||
|
||||
public Event<CreateTrackResourcesEvent> ProcessingStarted { get; private set; } = null!;
|
||||
public Event<TrackPictureProcessed> PictureProcessed { get; private set; } = null!;
|
||||
public Event<TrackAudioProcessed> AudioProcessed { get; private set; } = null!;
|
||||
public Event<TrackPictureProcessingFailed> PictureFailed { get; private set; } = null!;
|
||||
public Event<TrackAudioProcessingFailed> AudioFailed { get; private set; } = null!;
|
||||
Event(() => ProcessingStarted, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => PictureProcessed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => AudioProcessed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => PictureFailed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => AudioFailed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
|
||||
public TrackProcessingStateMachine()
|
||||
{
|
||||
InstanceState(state => state.CurrentState);
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.CreatedAt = DateTime.UtcNow;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
context.Saga.Bucket = context.Message.Bucket;
|
||||
context.Saga.PictureKey = context.Message.PictureDestinationKey;
|
||||
context.Saga.AudioKey = context.Message.AudioDestinationKey;
|
||||
})
|
||||
.TransitionTo(Processing));
|
||||
|
||||
Event(() => ProcessingStarted, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => PictureProcessed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => AudioProcessed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => PictureFailed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
Event(() => AudioFailed, config => config.CorrelateById(context => context.Message.TrackId));
|
||||
During(Processing,
|
||||
When(PictureProcessed)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.PictureProcessed = true;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
})
|
||||
.If(context => context.Saga.AudioProcessed, binder => binder.Finalize()),
|
||||
When(AudioProcessed)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.AudioProcessed = true;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
})
|
||||
.If(context => context.Saga.PictureProcessed, binder => binder.Finalize()),
|
||||
When(PictureFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new TrackProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey,
|
||||
context.Saga.AudioKey)),
|
||||
When(AudioFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new TrackProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey,
|
||||
context.Saga.AudioKey)));
|
||||
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.CreatedAt = DateTime.UtcNow;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
context.Saga.Bucket = context.Message.Bucket;
|
||||
context.Saga.PictureKey = context.Message.PictureDestinationKey;
|
||||
context.Saga.AudioKey = context.Message.AudioDestinationKey;
|
||||
} )
|
||||
.TransitionTo(Processing));
|
||||
During(Failed,
|
||||
Ignore(PictureProcessed),
|
||||
Ignore(AudioProcessed),
|
||||
Ignore(PictureFailed),
|
||||
Ignore(AudioFailed));
|
||||
|
||||
During(Processing,
|
||||
When(PictureProcessed)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.PictureProcessed = true;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
} )
|
||||
.If(context => context.Saga.AudioProcessed, binder => binder.Finalize()),
|
||||
When(AudioProcessed)
|
||||
.Then(context =>
|
||||
{
|
||||
context.Saga.AudioProcessed = true;
|
||||
context.Saga.UpdatedAt = DateTime.UtcNow;
|
||||
} )
|
||||
.If(context => context.Saga.PictureProcessed, binder => binder.Finalize()),
|
||||
When(PictureFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new TrackProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey,
|
||||
context.Saga.AudioKey)),
|
||||
When(AudioFailed)
|
||||
.Then(context => context.Saga.UpdatedAt = DateTime.UtcNow)
|
||||
.TransitionTo(Failed)
|
||||
.Publish(context => new TrackProcessingFailed(
|
||||
context.Saga.CorrelationId,
|
||||
context.Saga.Bucket,
|
||||
context.Saga.PictureKey,
|
||||
context.Saga.AudioKey)));
|
||||
|
||||
During(Failed,
|
||||
Ignore(PictureProcessed),
|
||||
Ignore(AudioProcessed),
|
||||
Ignore(PictureFailed),
|
||||
Ignore(AudioFailed));
|
||||
|
||||
SetCompletedWhenFinalized();
|
||||
}
|
||||
SetCompletedWhenFinalized();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user