Fix processing pipeline: report album failures, fault handling on create slips, config key names, audio duration
This commit is contained in:
@@ -16,10 +16,10 @@ public class TemporalUploadsCleanUpJob(
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
logger.LogInformation("TemporalUploadsCleanUpJob started (interval: {Interval}s, prefix: {Prefix})",
|
||||
uploadIntentConfiguration.TemporalCleanUpJobIntervalSeconds,
|
||||
uploadIntentConfiguration.TemporalRootPrefix);
|
||||
uploadIntentConfiguration.TempCleanupJobIntervalSeconds,
|
||||
uploadIntentConfiguration.TempRootPrefix);
|
||||
|
||||
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(uploadIntentConfiguration.TemporalCleanUpJobIntervalSeconds));
|
||||
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(uploadIntentConfiguration.TempCleanupJobIntervalSeconds));
|
||||
|
||||
do
|
||||
{
|
||||
@@ -40,13 +40,13 @@ public class TemporalUploadsCleanUpJob(
|
||||
await using var scope = scopeFactory.CreateAsyncScope();
|
||||
var storageService = scope.ServiceProvider.GetRequiredService<IStorageService>();
|
||||
|
||||
var cutOff = DateTime.UtcNow.AddDays(-uploadIntentConfiguration.TemporalUploadsRetentionDays);
|
||||
var cutOff = DateTime.UtcNow.AddDays(-uploadIntentConfiguration.TempUploadsRetentionDays);
|
||||
var deleted = 0;
|
||||
var errors = 0;
|
||||
|
||||
await foreach (var (key, lastModified) in storageService.ListObjectsAsync(
|
||||
storageConfiguration.Bucket,
|
||||
uploadIntentConfiguration.TemporalRootPrefix,
|
||||
uploadIntentConfiguration.TempRootPrefix,
|
||||
cancellationToken))
|
||||
{
|
||||
if (lastModified >= cutOff)
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ internal class TranscodeAudioActivity(
|
||||
var log = new TranscodeAudioLog(workingDirectory);
|
||||
return executeContext.CompletedWithVariables(log, new Dictionary<string, object>
|
||||
{
|
||||
[RoutingSlipVariableNames.Audio.DurationSeconds] = (int)Math.Round(transcodeResult.Duration.TotalSeconds)
|
||||
[RoutingSlipVariableNames.Audio.DurationSeconds] = transcodeResult.Duration.TotalSeconds
|
||||
});
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
+1
-5
@@ -38,11 +38,7 @@ internal class UpdateTrackAudioActivity(
|
||||
|
||||
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();
|
||||
throw new InvalidOperationException($"Audio folder key is empty for track {track.Id}");
|
||||
}
|
||||
|
||||
try
|
||||
|
||||
+22
@@ -32,6 +32,28 @@ public class ProcessingSlipFaultConsumer : IConsumer<RoutingSlipFaulted>
|
||||
case RoutingSlipVariableNames.ProcessKinds.PlayListPicture:
|
||||
await context.Publish(new PlayListPictureProcessingFailed(subjectId));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.AlbumPicture:
|
||||
await context.Publish(new AlbumPictureProcessingFailed(subjectId));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.TrackCreation:
|
||||
await context.Publish(new TrackProcessingFailed(
|
||||
subjectId, Variable(variables, RoutingSlipVariableNames.Workflow.Bucket),
|
||||
Variable(variables, RoutingSlipVariableNames.Workflow.PictureKey),
|
||||
Variable(variables, RoutingSlipVariableNames.Workflow.AudioKey)));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.AlbumCreation:
|
||||
await context.Publish(new AlbumProcessingFailed(
|
||||
subjectId, Variable(variables, RoutingSlipVariableNames.Workflow.Bucket),
|
||||
Variable(variables, RoutingSlipVariableNames.Workflow.PictureKey)));
|
||||
break;
|
||||
case RoutingSlipVariableNames.ProcessKinds.PlayListCreation:
|
||||
await context.Publish(new PlayListProcessingFailed(
|
||||
subjectId, Variable(variables, RoutingSlipVariableNames.Workflow.Bucket),
|
||||
Variable(variables, RoutingSlipVariableNames.Workflow.PictureKey)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? Variable(IDictionary<string, object> variables, string name) =>
|
||||
variables.TryGetValue(name, out var value) ? value?.ToString() : null;
|
||||
}
|
||||
|
||||
+14
-3
@@ -22,7 +22,8 @@ public class AlbumPictureSourceRoutingSlipBuilder
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
correlationId,
|
||||
RoutingSlipVariableNames.ProcessKinds.AlbumCreation);
|
||||
|
||||
public RoutingSlipBuilder Build(UpdateAlbumPictureSourceEvent message, Guid? correlationId)
|
||||
=> BuildSlip(
|
||||
@@ -34,7 +35,8 @@ public class AlbumPictureSourceRoutingSlipBuilder
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
correlationId,
|
||||
RoutingSlipVariableNames.ProcessKinds.AlbumPicture);
|
||||
|
||||
private static RoutingSlipBuilder BuildSlip(
|
||||
Guid albumId,
|
||||
@@ -45,7 +47,8 @@ public class AlbumPictureSourceRoutingSlipBuilder
|
||||
ImageSize small,
|
||||
ImageSize medium,
|
||||
ImageSize large,
|
||||
Guid? correlationId)
|
||||
Guid? correlationId,
|
||||
string processKind)
|
||||
{
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
@@ -79,6 +82,14 @@ public class AlbumPictureSourceRoutingSlipBuilder
|
||||
medium,
|
||||
large));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, albumId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, processKind);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, bucket);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, pictureDestinationKey);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -57,6 +57,15 @@ public class CreateTrackRoutingSlipBuilder
|
||||
message.Medium,
|
||||
message.Large));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackCreation);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, message.Bucket);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, message.PictureDestinationKey);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.AudioKey, message.AudioDestinationKey);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -22,7 +22,8 @@ public class PlayListPictureSourceRoutingSlipBuilder
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
correlationId,
|
||||
RoutingSlipVariableNames.ProcessKinds.PlayListCreation);
|
||||
|
||||
public RoutingSlipBuilder Build(UpdatePlayListPictureSourceEvent message, Guid? correlationId)
|
||||
=> BuildSlip(
|
||||
@@ -34,7 +35,8 @@ public class PlayListPictureSourceRoutingSlipBuilder
|
||||
message.Small,
|
||||
message.Medium,
|
||||
message.Large,
|
||||
correlationId);
|
||||
correlationId,
|
||||
RoutingSlipVariableNames.ProcessKinds.PlayListPicture);
|
||||
|
||||
private static RoutingSlipBuilder BuildSlip(
|
||||
Guid playListId,
|
||||
@@ -45,7 +47,8 @@ public class PlayListPictureSourceRoutingSlipBuilder
|
||||
ImageSize small,
|
||||
ImageSize medium,
|
||||
ImageSize large,
|
||||
Guid? correlationId)
|
||||
Guid? correlationId,
|
||||
string processKind)
|
||||
{
|
||||
var routingSlipBuilder = new RoutingSlipBuilder(NewId.NextGuid());
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.CorrelationId, correlationId ?? Guid.Empty);
|
||||
@@ -79,6 +82,14 @@ public class PlayListPictureSourceRoutingSlipBuilder
|
||||
medium,
|
||||
large));
|
||||
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, playListId);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, processKind);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.Bucket, bucket);
|
||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.PictureKey, pictureDestinationKey);
|
||||
routingSlipBuilder.AddSubscription(
|
||||
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||
RoutingSlipEvents.Faulted);
|
||||
|
||||
return routingSlipBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ internal static class RoutingSlipVariableNames
|
||||
internal const string CorrelationId = "Workflow.CorrelationId";
|
||||
internal const string SubjectId = "Workflow.SubjectId";
|
||||
internal const string ProcessKind = "Workflow.ProcessKind";
|
||||
internal const string Bucket = "Workflow.Bucket";
|
||||
internal const string PictureKey = "Workflow.PictureKey";
|
||||
internal const string AudioKey = "Workflow.AudioKey";
|
||||
}
|
||||
|
||||
internal static class ProcessKinds
|
||||
@@ -16,6 +19,9 @@ internal static class RoutingSlipVariableNames
|
||||
internal const string TrackAudio = "TrackAudio";
|
||||
internal const string PlayListPicture = "PlayListPicture";
|
||||
internal const string AlbumPicture = "AlbumPicture";
|
||||
internal const string TrackCreation = "TrackCreation";
|
||||
internal const string AlbumCreation = "AlbumCreation";
|
||||
internal const string PlayListCreation = "PlayListCreation";
|
||||
}
|
||||
|
||||
internal static class Audio
|
||||
|
||||
+10
-2
@@ -17,8 +17,16 @@ public sealed class AlbumProcessingStateMachine : MassTransitStateMachine<AlbumP
|
||||
InstanceState(state => state.CurrentState);
|
||||
|
||||
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));
|
||||
Event(() => PictureProcessed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.AlbumId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
Event(() => PictureFailed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.AlbumId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
|
||||
+10
-2
@@ -17,8 +17,16 @@ public sealed class PlayListProcessingStateMachine : MassTransitStateMachine<Pla
|
||||
InstanceState(state => state.CurrentState);
|
||||
|
||||
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));
|
||||
Event(() => PictureProcessed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.PlayListId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
Event(() => PictureFailed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.PlayListId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
|
||||
+20
-4
@@ -19,10 +19,26 @@ public sealed class TrackProcessingStateMachine : MassTransitStateMachine<TrackP
|
||||
InstanceState(state => state.CurrentState);
|
||||
|
||||
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));
|
||||
Event(() => PictureProcessed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.TrackId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
Event(() => AudioProcessed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.TrackId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
Event(() => PictureFailed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.TrackId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
Event(() => AudioFailed, config =>
|
||||
{
|
||||
config.CorrelateById(context => context.Message.TrackId);
|
||||
config.OnMissingInstance(instance => instance.Discard());
|
||||
});
|
||||
|
||||
Initially(
|
||||
When(ProcessingStarted)
|
||||
|
||||
Reference in New Issue
Block a user