feat(infra): playlist processing saga + generalize fault handling (phase 3)
Adds the PlayList picture-processing lifecycle saga (correlated by PlayListId)
mirroring the track one, and generalizes the failure plumbing:
- Rename the track fault translator to ProcessingSlipFaultConsumer and use a
generic Workflow.SubjectId variable + ProcessKind; it now emits typed
Track{Picture,Audio}/PlayListPicture ProcessingFailed events for all slips
- PlayListProcessingStateMachine (+ EF-persisted PlayListProcessingState,
migration): starts on CreatePlayListResourcesEvent, finalizes on
PlayListPictureProcessed, and on failure marks the playlist Failed and
removes the orphaned final picture (PlayListProcessingFailedConsumer +
MarkPlayListAsFailedActivity)
- UpdatePlayListPictureActivity publishes PlayListPictureProcessed on success
- Picture slip carries SubjectId + PlayListPicture kind + fault subscription
Verified end-to-end in Docker (RabbitMQ + migrated Postgres): both saga
endpoints, the fault translator and cleanup consumers configure, and an
addressing cross-check confirms all 21 activity execute queues the builders
address exist (caught + fixed a kebab mismatch on mark-play-list-as-failed).
Build: 0 warnings, 0 errors.
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Musify.Application.Events
|
||||||
|
{
|
||||||
|
public record PlayListPictureProcessed(Guid PlayListId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Musify.Application.Events
|
||||||
|
{
|
||||||
|
public record PlayListPictureProcessingFailed(Guid PlayListId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Musify.Application.Events
|
||||||
|
{
|
||||||
|
public record PlayListProcessingFailed(
|
||||||
|
Guid PlayListId,
|
||||||
|
string? Bucket,
|
||||||
|
string? PictureKey);
|
||||||
|
}
|
||||||
+7
@@ -1,6 +1,7 @@
|
|||||||
using MassTransit;
|
using MassTransit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Musify.Application.Contracts;
|
using Musify.Application.Contracts;
|
||||||
|
using Musify.Application.Events;
|
||||||
using Musify.Infrastructure.MassTransit.Arguments;
|
using Musify.Infrastructure.MassTransit.Arguments;
|
||||||
using Musify.Infrastructure.MassTransit.Logs;
|
using Musify.Infrastructure.MassTransit.Logs;
|
||||||
|
|
||||||
@@ -8,6 +9,7 @@ namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
|||||||
{
|
{
|
||||||
internal class UpdatePlayListPictureActivity(
|
internal class UpdatePlayListPictureActivity(
|
||||||
IDatabase database,
|
IDatabase database,
|
||||||
|
IPublishEndpoint publishEndpoint,
|
||||||
ILogger<UpdatePlayListPictureActivity> logger)
|
ILogger<UpdatePlayListPictureActivity> logger)
|
||||||
: IActivity<UpdatePlayListPictureArguments, UpdatePlayListPictureLog>
|
: IActivity<UpdatePlayListPictureArguments, UpdatePlayListPictureLog>
|
||||||
{
|
{
|
||||||
@@ -52,6 +54,11 @@ namespace Musify.Infrastructure.MassTransit.Activities.Pictures
|
|||||||
|
|
||||||
logger.LogInformation("Updated playlist {PlayListId} pictures",
|
logger.LogInformation("Updated playlist {PlayListId} pictures",
|
||||||
executeContext.Arguments.PlayListId);
|
executeContext.Arguments.PlayListId);
|
||||||
|
|
||||||
|
await publishEndpoint.Publish(
|
||||||
|
new PlayListPictureProcessed(executeContext.Arguments.PlayListId),
|
||||||
|
executeContext.CancellationToken);
|
||||||
|
|
||||||
return executeContext.Completed();
|
return executeContext.Completed();
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
using MassTransit;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Musify.Application.Contracts;
|
||||||
|
using Musify.Domain.ValueObjects;
|
||||||
|
using Musify.Infrastructure.MassTransit.Arguments;
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.MassTransit.Activities.PlayLists
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
var playList = await database.PlayLists
|
||||||
|
.SingleOrDefaultAsync(p => p.Id == executeContext.Arguments.PlayListId, executeContext.CancellationToken);
|
||||||
|
|
||||||
|
if (playList is not null)
|
||||||
|
{
|
||||||
|
playList.LifeCycleStatus = LifeCycleStatus.Failed;
|
||||||
|
await database.SaveChangesAsync(executeContext.CancellationToken);
|
||||||
|
logger.LogInformation("Marked playlist {PlayListId} as failed", executeContext.Arguments.PlayListId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeContext.Completed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Musify.Infrastructure.MassTransit.Arguments
|
||||||
|
{
|
||||||
|
public record MarkPlayListAsFailedArguments(Guid PlayListId);
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
using MassTransit;
|
||||||
|
using MassTransit.Courier.Contracts;
|
||||||
|
using Musify.Application.Events;
|
||||||
|
using Musify.Infrastructure.MassTransit.Activities.Files;
|
||||||
|
using Musify.Infrastructure.MassTransit.Activities.PlayLists;
|
||||||
|
using Musify.Infrastructure.MassTransit.Arguments;
|
||||||
|
using Musify.Infrastructure.MassTransit.RoutingSlip;
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||||
|
{
|
||||||
|
public class PlayListProcessingFailedConsumer(IBus bus) : IConsumer<PlayListProcessingFailed>
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-6
@@ -4,9 +4,9 @@ using Musify.Application.Events;
|
|||||||
|
|
||||||
namespace Musify.Infrastructure.MassTransit.Consumers
|
namespace Musify.Infrastructure.MassTransit.Consumers
|
||||||
{
|
{
|
||||||
public class TrackProcessingSlipFaultConsumer : IConsumer<RoutingSlipFaulted>
|
public class ProcessingSlipFaultConsumer : IConsumer<RoutingSlipFaulted>
|
||||||
{
|
{
|
||||||
public const string QueueName = "track-processing-slip-fault";
|
public const string QueueName = "processing-slip-fault";
|
||||||
|
|
||||||
public async Task Consume(ConsumeContext<RoutingSlipFaulted> context)
|
public async Task Consume(ConsumeContext<RoutingSlipFaulted> context)
|
||||||
{
|
{
|
||||||
@@ -15,17 +15,20 @@ namespace Musify.Infrastructure.MassTransit.Consumers
|
|||||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.ProcessKind, out var kindObject))
|
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.ProcessKind, out var kindObject))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.TrackId, out var trackObject)
|
if (!variables.TryGetValue(RoutingSlipVariableNames.Workflow.SubjectId, out var subjectObject)
|
||||||
|| !Guid.TryParse(trackObject?.ToString(), out var trackId))
|
|| !Guid.TryParse(subjectObject?.ToString(), out var subjectId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (kindObject?.ToString())
|
switch (kindObject?.ToString())
|
||||||
{
|
{
|
||||||
case RoutingSlipVariableNames.ProcessKinds.TrackPicture:
|
case RoutingSlipVariableNames.ProcessKinds.TrackPicture:
|
||||||
await context.Publish(new TrackPictureProcessingFailed(trackId));
|
await context.Publish(new TrackPictureProcessingFailed(subjectId));
|
||||||
break;
|
break;
|
||||||
case RoutingSlipVariableNames.ProcessKinds.TrackAudio:
|
case RoutingSlipVariableNames.ProcessKinds.TrackAudio:
|
||||||
await context.Publish(new TrackAudioProcessingFailed(trackId));
|
await context.Publish(new TrackAudioProcessingFailed(subjectId));
|
||||||
|
break;
|
||||||
|
case RoutingSlipVariableNames.ProcessKinds.PlayListPicture:
|
||||||
|
await context.Publish(new PlayListPictureProcessingFailed(subjectId));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-1
@@ -36,8 +36,9 @@ namespace Musify.Infrastructure.MassTransit
|
|||||||
options.AddConsumer<CreateTrackConsumer>();
|
options.AddConsumer<CreateTrackConsumer>();
|
||||||
options.AddConsumer<CreatePlayListConsumer>();
|
options.AddConsumer<CreatePlayListConsumer>();
|
||||||
options.AddConsumer<UpdatePlayListPictureSourceConsumer>();
|
options.AddConsumer<UpdatePlayListPictureSourceConsumer>();
|
||||||
options.AddConsumer<TrackProcessingSlipFaultConsumer>();
|
options.AddConsumer<ProcessingSlipFaultConsumer>();
|
||||||
options.AddConsumer<TrackProcessingFailedConsumer>();
|
options.AddConsumer<TrackProcessingFailedConsumer>();
|
||||||
|
options.AddConsumer<PlayListProcessingFailedConsumer>();
|
||||||
|
|
||||||
options.AddExecuteActivity<RemoveFileFromBucketActivity, RemoveFileFromBucketArguments>();
|
options.AddExecuteActivity<RemoveFileFromBucketActivity, RemoveFileFromBucketArguments>();
|
||||||
options.AddExecuteActivity<GenerateAudioWorkflowPathsActivity, GenerateAudioWorkflowPathsArguments>();
|
options.AddExecuteActivity<GenerateAudioWorkflowPathsActivity, GenerateAudioWorkflowPathsArguments>();
|
||||||
@@ -49,6 +50,7 @@ namespace Musify.Infrastructure.MassTransit
|
|||||||
options.AddExecuteActivity<PublishTrackProcessingEventsActivity, PublishTrackProcessingEventsArguments>();
|
options.AddExecuteActivity<PublishTrackProcessingEventsActivity, PublishTrackProcessingEventsArguments>();
|
||||||
options.AddExecuteActivity<PublishPlayListPictureProcessingEventActivity, PublishPlayListPictureProcessingEventArguments>();
|
options.AddExecuteActivity<PublishPlayListPictureProcessingEventActivity, PublishPlayListPictureProcessingEventArguments>();
|
||||||
options.AddExecuteActivity<MarkTrackAsFailedActivity, MarkTrackAsFailedArguments>();
|
options.AddExecuteActivity<MarkTrackAsFailedActivity, MarkTrackAsFailedArguments>();
|
||||||
|
options.AddExecuteActivity<MarkPlayListAsFailedActivity, MarkPlayListAsFailedArguments>();
|
||||||
|
|
||||||
options.AddActivity<ResizePictureActivity, ResizePictureLocalArguments, ResizePictureLog>();
|
options.AddActivity<ResizePictureActivity, ResizePictureLocalArguments, ResizePictureLog>();
|
||||||
options.AddActivity<UpdatePlayListPictureActivity, UpdatePlayListPictureArguments, UpdatePlayListPictureLog>();
|
options.AddActivity<UpdatePlayListPictureActivity, UpdatePlayListPictureArguments, UpdatePlayListPictureLog>();
|
||||||
|
|||||||
+8
@@ -75,6 +75,14 @@ namespace Musify.Infrastructure.MassTransit
|
|||||||
repository.UsePostgres();
|
repository.UsePostgres();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
options.AddSagaStateMachine<PlayListProcessingStateMachine, PlayListProcessingState>()
|
||||||
|
.EntityFrameworkRepository(repository =>
|
||||||
|
{
|
||||||
|
repository.ConcurrencyMode = ConcurrencyMode.Pessimistic;
|
||||||
|
repository.ExistingDbContext<Database>();
|
||||||
|
repository.UsePostgres();
|
||||||
|
});
|
||||||
|
|
||||||
options.AddConfigureEndpointsCallback((registrationContext, _, endpointConfigurator) =>
|
options.AddConfigureEndpointsCallback((registrationContext, _, endpointConfigurator) =>
|
||||||
{
|
{
|
||||||
UseStandardRetry(endpointConfigurator);
|
UseStandardRetry(endpointConfigurator);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip
|
|||||||
internal const string MarkTrackAsFailed = "MarkTrackAsFailed";
|
internal const string MarkTrackAsFailed = "MarkTrackAsFailed";
|
||||||
internal const string DeleteTrackFromDb = "DeleteTrackFromDb";
|
internal const string DeleteTrackFromDb = "DeleteTrackFromDb";
|
||||||
internal const string MarkPlayListAsRemoving = "MarkPlayListAsRemoving";
|
internal const string MarkPlayListAsRemoving = "MarkPlayListAsRemoving";
|
||||||
|
internal const string MarkPlayListAsFailed = "MarkPlayListAsFailed";
|
||||||
internal const string DeletePlayListFromDb = "DeletePlayListFromDb";
|
internal const string DeletePlayListFromDb = "DeletePlayListFromDb";
|
||||||
|
|
||||||
internal const string GenerateAudioWorkflowPaths = "GenerateAudioWorkflowPaths";
|
internal const string GenerateAudioWorkflowPaths = "GenerateAudioWorkflowPaths";
|
||||||
|
|||||||
+2
-2
@@ -60,10 +60,10 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
|||||||
message.TrackId,
|
message.TrackId,
|
||||||
message.DestinationFolderKey));
|
message.DestinationFolderKey));
|
||||||
|
|
||||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.TrackId, message.TrackId);
|
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackAudio);
|
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackAudio);
|
||||||
routingSlipBuilder.AddSubscription(
|
routingSlipBuilder.AddSubscription(
|
||||||
EndpointHelper.BuildConsumerUri(TrackProcessingSlipFaultConsumer.QueueName),
|
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||||
RoutingSlipEvents.Faulted);
|
RoutingSlipEvents.Faulted);
|
||||||
|
|
||||||
return routingSlipBuilder;
|
return routingSlipBuilder;
|
||||||
|
|||||||
+8
-2
@@ -32,10 +32,10 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
|||||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
||||||
|
|
||||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.TrackId, message.TrackId);
|
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.SubjectId, message.TrackId);
|
||||||
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackPicture);
|
routingSlipBuilder.AddVariable(RoutingSlipVariableNames.Workflow.ProcessKind, RoutingSlipVariableNames.ProcessKinds.TrackPicture);
|
||||||
routingSlipBuilder.AddSubscription(
|
routingSlipBuilder.AddSubscription(
|
||||||
EndpointHelper.BuildConsumerUri(TrackProcessingSlipFaultConsumer.QueueName),
|
EndpointHelper.BuildConsumerUri(ProcessingSlipFaultConsumer.QueueName),
|
||||||
RoutingSlipEvents.Faulted);
|
RoutingSlipEvents.Faulted);
|
||||||
|
|
||||||
return routingSlipBuilder;
|
return routingSlipBuilder;
|
||||||
@@ -61,6 +61,12 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
|
|||||||
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
RoutingSlipVariableNames.Picture.MediumResizedFilePath,
|
||||||
RoutingSlipVariableNames.Picture.LargeResizedFilePath));
|
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;
|
return routingSlipBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Musify.Infrastructure.MassTransit
|
|||||||
{
|
{
|
||||||
internal const string TemporalDirectory = "Workflow.TemporalDirectory";
|
internal const string TemporalDirectory = "Workflow.TemporalDirectory";
|
||||||
internal const string CorrelationId = "Workflow.CorrelationId";
|
internal const string CorrelationId = "Workflow.CorrelationId";
|
||||||
internal const string TrackId = "Workflow.TrackId";
|
internal const string SubjectId = "Workflow.SubjectId";
|
||||||
internal const string ProcessKind = "Workflow.ProcessKind";
|
internal const string ProcessKind = "Workflow.ProcessKind";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ namespace Musify.Infrastructure.MassTransit
|
|||||||
{
|
{
|
||||||
internal const string TrackPicture = "TrackPicture";
|
internal const string TrackPicture = "TrackPicture";
|
||||||
internal const string TrackAudio = "TrackAudio";
|
internal const string TrackAudio = "TrackAudio";
|
||||||
|
internal const string PlayListPicture = "PlayListPicture";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class Audio
|
internal static class Audio
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using MassTransit;
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||||
|
{
|
||||||
|
public class PlayListProcessingState : SagaStateMachineInstance
|
||||||
|
{
|
||||||
|
public Guid CorrelationId { get; set; }
|
||||||
|
|
||||||
|
public string CurrentState { get; set; } = null!;
|
||||||
|
|
||||||
|
public string? Bucket { get; set; }
|
||||||
|
|
||||||
|
public string? PictureKey { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using MassTransit;
|
||||||
|
using Musify.Application.Events;
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.MassTransit.Sagas
|
||||||
|
{
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
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(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,11 @@ namespace Musify.Infrastructure.Persistence
|
|||||||
trackProcessing.HasKey(state => state.CorrelationId);
|
trackProcessing.HasKey(state => state.CorrelationId);
|
||||||
trackProcessing.Property(state => state.CorrelationId).ValueGeneratedNever();
|
trackProcessing.Property(state => state.CorrelationId).ValueGeneratedNever();
|
||||||
trackProcessing.Property(state => state.CurrentState).HasMaxLength(64);
|
trackProcessing.Property(state => state.CurrentState).HasMaxLength(64);
|
||||||
|
|
||||||
|
var playListProcessing = modelBuilder.Entity<PlayListProcessingState>();
|
||||||
|
playListProcessing.HasKey(state => state.CorrelationId);
|
||||||
|
playListProcessing.Property(state => state.CorrelationId).ValueGeneratedNever();
|
||||||
|
playListProcessing.Property(state => state.CurrentState).HasMaxLength(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<User> Users => Set<User>();
|
public DbSet<User> Users => Set<User>();
|
||||||
|
|||||||
+646
@@ -0,0 +1,646 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Musify.Infrastructure.Persistence;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.Persistence.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(Database))]
|
||||||
|
[Migration("20260705125356_AddPlayListProcessingStateSaga")]
|
||||||
|
partial class AddPlayListProcessingStateSaga
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Consumed")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<Guid>("ConsumerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Delivered")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ExpirationTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<long?>("LastSequenceNumber")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<Guid>("LockId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("MessageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("ReceiveCount")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Received")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<byte[]>("RowVersion")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Delivered");
|
||||||
|
|
||||||
|
b.ToTable("InboxState");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("SequenceNumber")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("SequenceNumber"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ContentType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("ConversationId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CorrelationId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("DestinationAddress")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("EnqueueTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ExpirationTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("FaultAddress")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("Headers")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("InboxConsumerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("InboxMessageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("InitiatorId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("MessageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("MessageType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OutboxId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Properties")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("RequestId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("ResponseAddress")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("SourceAddress")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.HasKey("SequenceNumber");
|
||||||
|
|
||||||
|
b.HasIndex("EnqueueTime");
|
||||||
|
|
||||||
|
b.HasIndex("ExpirationTime");
|
||||||
|
|
||||||
|
b.HasIndex("OutboxId", "SequenceNumber")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("OutboxMessage");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("OutboxId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Created")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Delivered")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<long?>("LastSequenceNumber")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<Guid>("LockId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<byte[]>("RowVersion")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("bytea");
|
||||||
|
|
||||||
|
b.HasKey("OutboxId");
|
||||||
|
|
||||||
|
b.HasIndex("Created");
|
||||||
|
|
||||||
|
b.ToTable("OutboxState");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
b.Property<string>("LargePictureName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<int>("LifeCycleStatus")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("MediumPictureName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<string>("OriginalPictureName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("SmallPictureName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("PlayLists");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<Guid>("PlayListId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Position")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<Guid>("TrackId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlayListId");
|
||||||
|
|
||||||
|
b.HasIndex("TrackId");
|
||||||
|
|
||||||
|
b.ToTable("PlayListHasTrack");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("AudioFolderName")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<int>("AudioTranscodeProcessingStatus")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("LargePictureName")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastRetryAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<int>("LifeCycleStatus")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("MediumPictureName")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedTitle")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<string>("OriginalAudioName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("OriginalPictureName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<int>("PicturesProcessingStatus")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("RetryCount")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("SmallPictureName")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Tracks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.Upload", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Bucket")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ContentType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("State")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Upload");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Bucket")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("character varying(128)");
|
||||||
|
|
||||||
|
b.Property<string>("ContentType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("character varying(128)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<long?>("ExpectedSizeBytes")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ExpiresAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.Property<string>("ObjectName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("character varying(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Purpose")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("UploadIntents");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.HasMaxLength(48)
|
||||||
|
.HasColumnType("character varying(48)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(48)
|
||||||
|
.HasColumnType("character varying(48)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(48)
|
||||||
|
.HasColumnType("character varying(48)");
|
||||||
|
|
||||||
|
b.Property<string>("ProfilePictureUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("SecondName")
|
||||||
|
.HasMaxLength(48)
|
||||||
|
.HasColumnType("character varying(48)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("TrackId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TrackId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("UserHasTrack");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.PlayListProcessingState", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("CorrelationId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Bucket")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("CurrentState")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("PictureKey")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("CorrelationId");
|
||||||
|
|
||||||
|
b.ToTable("PlayListProcessingState");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.TrackProcessingState", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("CorrelationId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("AudioKey")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("AudioProcessed")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("Bucket")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("CurrentState")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("PictureKey")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("PictureProcessed")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("CorrelationId");
|
||||||
|
|
||||||
|
b.ToTable("TrackProcessingState");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OutboxId");
|
||||||
|
|
||||||
|
b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("InboxMessageId", "InboxConsumerId")
|
||||||
|
.HasPrincipalKey("MessageId", "ConsumerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||||
|
.WithMany("PlayLists")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Musify.Domain.Entities.PlayList", "PlayList")
|
||||||
|
.WithMany("PlayListTracks")
|
||||||
|
.HasForeignKey("PlayListId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||||
|
.WithMany("PlayListTracks")
|
||||||
|
.HasForeignKey("TrackId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("PlayList");
|
||||||
|
|
||||||
|
b.Navigation("Track");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Musify.Domain.Entities.Track", "Track")
|
||||||
|
.WithMany("UserTracks")
|
||||||
|
.HasForeignKey("TrackId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Musify.Domain.Entities.User", "User")
|
||||||
|
.WithMany("UserTracks")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Track");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PlayListTracks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PlayListTracks");
|
||||||
|
|
||||||
|
b.Navigation("UserTracks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PlayLists");
|
||||||
|
|
||||||
|
b.Navigation("UserTracks");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.Persistence.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddPlayListProcessingStateSaga : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PlayListProcessingState",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
CorrelationId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CurrentState = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||||
|
Bucket = table.Column<string>(type: "text", nullable: true),
|
||||||
|
PictureKey = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_PlayListProcessingState", x => x.CorrelationId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PlayListProcessingState");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -484,6 +484,33 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
|||||||
b.ToTable("UserHasTrack");
|
b.ToTable("UserHasTrack");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.PlayListProcessingState", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("CorrelationId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Bucket")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("CurrentState")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("character varying(64)");
|
||||||
|
|
||||||
|
b.Property<string>("PictureKey")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("CorrelationId");
|
||||||
|
|
||||||
|
b.ToTable("PlayListProcessingState");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.TrackProcessingState", b =>
|
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.TrackProcessingState", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("CorrelationId")
|
b.Property<Guid>("CorrelationId")
|
||||||
|
|||||||
Reference in New Issue
Block a user