├── tests ├── Sample.Tests │ ├── Usings.cs │ ├── UnitTest1.cs │ └── Sample.Tests.csproj └── SampleRequests.http ├── src ├── Sample.Components │ ├── ComponentsNamespace.cs │ ├── Activities │ │ ├── AssignWaiverArguments.cs │ │ ├── EventRegistrationLog.cs │ │ ├── LicenseVerificationArguments.cs │ │ ├── ProcessPaymentArguments.cs │ │ ├── EventRegistrationArguments.cs │ │ ├── ProcessPaymentLog.cs │ │ ├── AssignWaiverActivity.cs │ │ ├── LicenseVerificationActivity.cs │ │ ├── ProcessPaymentActivity.cs │ │ └── EventRegistrationActivity.cs │ ├── Services │ │ ├── ISecurePaymentInfoService.cs │ │ └── SecurePaymentInfoService.cs │ ├── IEndpointAddressProvider.cs │ ├── TransientException.cs │ ├── LongTransientException.cs │ ├── Sample.Components.csproj │ ├── DbEndpointAddressProvider.cs │ ├── StringExtensions.cs │ ├── StateMachines │ │ ├── RegistrationState.cs │ │ ├── RegistrationStateInstanceMap.cs │ │ └── RegistrationStateMachine.cs │ ├── CorrelationInitializer.cs │ ├── MigrationHostedService.cs │ ├── PartitionKeyExtensions.cs │ ├── Consumers │ │ ├── SubmitRegistrationConsumer.cs │ │ └── ProcessRegistrationConsumer.cs │ └── SampleDbContext.cs ├── Sample.Contracts │ ├── SubmitRegistration.cs │ ├── RegistrationReceived.cs │ ├── ProcessRegistration.cs │ ├── RetryDelayExpired.cs │ ├── GetRegistrationStatus.cs │ ├── RegistrationPaymentFailed.cs │ ├── RegistrationLicenseVerificationFailed.cs │ ├── RegistrationStatus.cs │ ├── SecurePaymentInfo.cs │ ├── Sample.Contracts.csproj │ ├── RegistrationCompleted.cs │ └── RegistrationDetail.cs ├── Sample.Api │ ├── appsettings.json │ ├── Properties │ │ └── launchSettings.json │ ├── Sample.Api.csproj │ ├── PgSqlTransportExtensions.cs │ ├── Controllers │ │ └── RegistrationController.cs │ ├── Program.cs │ └── Migrations │ │ ├── 20241004184848_Updated.cs │ │ ├── 20230706011449_Initial.cs │ │ ├── 20230706011449_Initial.Designer.cs │ │ ├── SampleDbContextModelSnapshot.cs │ │ └── 20241004184848_Updated.Designer.cs └── Sample.Api.SqlServer │ ├── appsettings.json │ ├── Properties │ └── launchSettings.json │ ├── Migrations │ ├── 20250211032911_Updated2.cs │ ├── 20241004184901_Updated.cs │ ├── 20230815145325_InitialSqlServer.cs │ ├── 20230815145325_InitialSqlServer.Designer.cs │ └── 20241004184901_Updated.Designer.cs │ ├── Sample.Api.SqlServer.csproj │ ├── SqlServerTransportExtensions.cs │ ├── Controllers │ └── RegistrationController.cs │ └── Program.cs ├── README.md ├── .gitignore ├── docker-compose.yml └── Sample-DbTransport.sln /tests/Sample.Tests/Usings.cs: -------------------------------------------------------------------------------- 1 | global using Xunit; -------------------------------------------------------------------------------- /src/Sample.Components/ComponentsNamespace.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | public struct ComponentsNamespace 4 | { 5 | } -------------------------------------------------------------------------------- /src/Sample.Contracts/SubmitRegistration.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | public record SubmitRegistration : 4 | RegistrationDetail; -------------------------------------------------------------------------------- /src/Sample.Contracts/RegistrationReceived.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | public record RegistrationReceived : 4 | RegistrationDetail; -------------------------------------------------------------------------------- /src/Sample.Contracts/ProcessRegistration.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | public record ProcessRegistration : 4 | RegistrationDetail 5 | { 6 | } -------------------------------------------------------------------------------- /src/Sample.Contracts/RetryDelayExpired.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | using System; 4 | 5 | 6 | public record RetryDelayExpired(Guid RegistrationId); -------------------------------------------------------------------------------- /src/Sample.Contracts/GetRegistrationStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | public record GetRegistrationStatus 4 | { 5 | public Guid SubmissionId { get; init; } 6 | } -------------------------------------------------------------------------------- /tests/Sample.Tests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Tests; 2 | 3 | public class UnitTest1 4 | { 5 | [Fact] 6 | public void Test1() 7 | { 8 | 9 | } 10 | } -------------------------------------------------------------------------------- /src/Sample.Api/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AllowedHosts": "*", 3 | "ConnectionStrings": { 4 | "Db": "host=localhost;user id=postgres;password=Password12!;database=sample;" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Sample.Components/Activities/AssignWaiverArguments.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | public record AssignWaiverArguments 4 | { 5 | public string? ParticipantEmailAddress { get; init; } 6 | public string? EventId { get; init; } 7 | } -------------------------------------------------------------------------------- /src/Sample.Components/Activities/EventRegistrationLog.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | public record EventRegistrationLog 4 | { 5 | public Guid? RegistrationId { get; init; } 6 | public string? ParticipantEmailAddress { get; init; } 7 | } -------------------------------------------------------------------------------- /src/Sample.Components/Services/ISecurePaymentInfoService.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Services; 2 | 3 | using Contracts; 4 | 5 | 6 | public interface ISecurePaymentInfoService 7 | { 8 | SecurePaymentInfo GetPaymentInfo(string? emailAddress, string? cardNumber); 9 | } -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AllowedHosts": "*", 3 | "ConnectionStrings": { 4 | "Db": "Server=tcp:localhost;Initial Catalog=sample;Persist Security Info=False;User ID=sa;Password=Password12!;TrustServerCertificate=True;Connection Timeout=30;" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Sample.Contracts/RegistrationPaymentFailed.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | using MassTransit; 4 | 5 | 6 | public record RegistrationPaymentFailed 7 | { 8 | public Guid SubmissionId { get; init; } 9 | 10 | public ExceptionInfo? ExceptionInfo { get; init; } 11 | } -------------------------------------------------------------------------------- /src/Sample.Contracts/RegistrationLicenseVerificationFailed.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | using MassTransit; 4 | 5 | 6 | public record RegistrationLicenseVerificationFailed 7 | { 8 | public Guid SubmissionId { get; init; } 9 | 10 | public ExceptionInfo? ExceptionInfo { get; init; } 11 | } -------------------------------------------------------------------------------- /src/Sample.Contracts/RegistrationStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | public record RegistrationStatus : 4 | RegistrationDetail 5 | { 6 | public string? Status { get; init; } 7 | public DateTime? ParticipantLicenseExpirationDate { get; init; } 8 | public Guid? RegistrationId { get; init; } 9 | } -------------------------------------------------------------------------------- /src/Sample.Components/Activities/LicenseVerificationArguments.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | public record LicenseVerificationArguments 4 | { 5 | public string? ParticipantLicenseNumber { get; init; } 6 | 7 | public string? EventType { get; init; } 8 | public string? ParticipantCategory { get; init; } 9 | } -------------------------------------------------------------------------------- /src/Sample.Components/IEndpointAddressProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using System; 4 | using MassTransit; 5 | 6 | 7 | public interface IEndpointAddressProvider 8 | { 9 | Uri GetExecuteEndpoint() 10 | where T : class, IExecuteActivity 11 | where TArguments : class; 12 | } -------------------------------------------------------------------------------- /src/Sample.Components/TransientException.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using System; 4 | 5 | 6 | [Serializable] 7 | public class TransientException : 8 | Exception 9 | { 10 | public TransientException() 11 | { 12 | } 13 | 14 | public TransientException(string message) 15 | : base(message) 16 | { 17 | } 18 | } -------------------------------------------------------------------------------- /src/Sample.Components/LongTransientException.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using System; 4 | 5 | 6 | [Serializable] 7 | public class LongTransientException : 8 | Exception 9 | { 10 | public LongTransientException() 11 | { 12 | } 13 | 14 | public LongTransientException(string message) 15 | : base(message) 16 | { 17 | } 18 | } -------------------------------------------------------------------------------- /src/Sample.Contracts/SecurePaymentInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | public record SecurePaymentInfo 4 | { 5 | public string? CardNumber { get; init; } 6 | public string? VerificationCode { get; init; } 7 | public string? CardholderName { get; init; } 8 | public int? ExpirationMonth { get; init; } 9 | public int? ExpirationYear { get; init; } 10 | } -------------------------------------------------------------------------------- /src/Sample.Contracts/Sample.Contracts.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MassTransit Database Transport Sample 2 | 3 | ## Getting Started 4 | 5 | 1. Run `docker compose up --build` to start the database engines. 6 | 2. Open the solution. 7 | 3. Build it (the NuGet packages should restore) 8 | 4. Run either the Sample.Api or Sample.Api.SqlServer project, depending upon which database you want to use. 9 | 5. Navigate to [`http://localhost:5010/swagger`](http://localhost:5010/swagger) to interact with the API. 10 | -------------------------------------------------------------------------------- /src/Sample.Components/Activities/ProcessPaymentArguments.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | public record ProcessPaymentArguments 4 | { 5 | public string? CardNumber { get; init; } 6 | public string? VerificationCode { get; init; } 7 | public string? CardholderName { get; init; } 8 | public int? ExpirationMonth { get; init; } 9 | public int? ExpirationYear { get; init; } 10 | 11 | public decimal? Amount { get; init; } 12 | } -------------------------------------------------------------------------------- /src/Sample.Api/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "http://localhost:5010", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "http://localhost:5010", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Sample.Contracts/RegistrationCompleted.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | using MassTransit.Courier.Contracts; 4 | 5 | 6 | public record RegistrationCompleted : 7 | RoutingSlipCompleted 8 | { 9 | public Guid SubmissionId { get; init; } 10 | public Guid TrackingNumber { get; init; } 11 | 12 | public DateTime Timestamp { get; set; } 13 | public TimeSpan Duration { get; set; } 14 | public IDictionary Variables { get; set; } = null!; 15 | } -------------------------------------------------------------------------------- /src/Sample.Components/Activities/EventRegistrationArguments.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | public record EventRegistrationArguments 4 | { 5 | public string? ParticipantEmailAddress { get; init; } 6 | 7 | public string? ParticipantLicenseNumber { get; init; } 8 | public DateTime? ParticipantLicenseExpirationDate { get; init; } 9 | 10 | public string? ParticipantCategory { get; init; } 11 | 12 | public string? EventId { get; init; } 13 | public string? RaceId { get; init; } 14 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | *.dotCover 4 | 5 | .vs 6 | 7 | bin 8 | obj 9 | _ReSharper* 10 | 11 | *.csproj.user 12 | *.resharper.user 13 | *.resharper 14 | *.ReSharper 15 | *.cache 16 | *~ 17 | *.swp 18 | *.bak 19 | *.orig 20 | 21 | **/BenchmarkDotNet.Artifacts/**/* 22 | 23 | # osx noise 24 | .DS_Store 25 | *.DS_Store 26 | *.DotSettings.user 27 | 28 | docs/.vuepress/dist 29 | .vscode 30 | .idea 31 | appsettings.Development.json 32 | 33 | node_modules 34 | *.iml 35 | *.log* 36 | .nuxt 37 | coverage 38 | dist 39 | sw.* 40 | .env 41 | .output 42 | -------------------------------------------------------------------------------- /src/Sample.Contracts/RegistrationDetail.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Contracts; 2 | 3 | using MassTransit; 4 | 5 | 6 | [ExcludeFromTopology] 7 | public record RegistrationDetail 8 | { 9 | public Guid SubmissionId { get; init; } 10 | 11 | public string? ParticipantEmailAddress { get; init; } 12 | public string? ParticipantLicenseNumber { get; init; } 13 | public string? ParticipantCategory { get; init; } 14 | 15 | public string? CardNumber { get; init; } 16 | 17 | public string? EventId { get; init; } 18 | public string? RaceId { get; init; } 19 | } -------------------------------------------------------------------------------- /tests/SampleRequests.http: -------------------------------------------------------------------------------- 1 | ### Create Registration 2 | POST http://localhost:5010/Registration 3 | Content-Type: application/json 4 | 5 | { 6 | "submissionId": "{{$random.uuid}}", 7 | "participantEmailAddress": "test@hello.com", 8 | "participantLicenseNumber": "LIC123", 9 | "participantCategory": "Road", 10 | "cardNumber": "4444-4444-4444-4444", 11 | "eventId": "E-123", 12 | "raceId": "R-456" 13 | } 14 | 15 | > {% client.global.set("submissionId", response.body.submissionId); %} 16 | 17 | ### Get Registration 18 | GET http://localhost:5010/Registration/{{submissionId}} 19 | -------------------------------------------------------------------------------- /src/Sample.Components/Activities/ProcessPaymentLog.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | public record ProcessPaymentLog 4 | { 5 | /// 6 | /// The date the charge was processed 7 | /// 8 | public DateTime? ChargeDate { get; init; } 9 | 10 | /// 11 | /// The authorization code received from the payment provider 12 | /// 13 | public string? AuthorizationCode { get; init; } 14 | 15 | /// 16 | /// The amount charged 17 | /// 18 | public decimal? Amount { get; init; } 19 | } -------------------------------------------------------------------------------- /src/Sample.Components/Sample.Components.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Sample.Components/Services/SecurePaymentInfoService.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Services; 2 | 3 | using Contracts; 4 | 5 | 6 | public class SecurePaymentInfoService : 7 | ISecurePaymentInfoService 8 | { 9 | public SecurePaymentInfo GetPaymentInfo(string? emailAddress, string? cardNumber) 10 | { 11 | return new SecurePaymentInfo 12 | { 13 | CardNumber = cardNumber, 14 | VerificationCode = "123", 15 | CardholderName = "FRANK UNDERHILL", 16 | ExpirationMonth = 12, 17 | ExpirationYear = 2023, 18 | }; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Sample.Components/DbEndpointAddressProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using MassTransit; 4 | 5 | 6 | public class DbEndpointAddressProvider : 7 | IEndpointAddressProvider 8 | { 9 | readonly IEndpointNameFormatter _formatter; 10 | 11 | public DbEndpointAddressProvider(IEndpointNameFormatter formatter) 12 | { 13 | _formatter = formatter; 14 | } 15 | 16 | public Uri GetExecuteEndpoint() 17 | where T : class, IExecuteActivity 18 | where TArguments : class 19 | { 20 | return new Uri($"queue:{_formatter.ExecuteActivity()}"); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Sample.Components/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using System.Text.RegularExpressions; 4 | 5 | 6 | public static partial class StringExtensions 7 | { 8 | public static string ToSnakeCase(this string input) 9 | { 10 | if (string.IsNullOrEmpty(input)) 11 | return input; 12 | 13 | var startUnderscores = MyRegex().Match(input); 14 | return startUnderscores + MyRegex1().Replace(input, "$1_$2").ToLower(); 15 | } 16 | 17 | [GeneratedRegex("^_+")] 18 | private static partial Regex MyRegex(); 19 | 20 | [GeneratedRegex("([a-z0-9])([A-Z])")] 21 | private static partial Regex MyRegex1(); 22 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | mssql: 3 | image: "mcr.microsoft.com/azure-sql-edge" 4 | networks: 5 | - sample-network 6 | environment: 7 | - "ACCEPT_EULA=Y" 8 | - "SA_PASSWORD=Password12!" 9 | ports: 10 | - "1433:1433" 11 | postgres: 12 | image: "postgres:14.7" 13 | networks: 14 | - sample-network 15 | environment: 16 | - "POSTGRES_USER=postgres" 17 | - "POSTGRES_PASSWORD=Password12!" 18 | - "POSTGRES_DB=sample" 19 | ports: 20 | - "5432:5432" 21 | healthcheck: 22 | test: [ "CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}" ] 23 | interval: 5s 24 | timeout: 10s 25 | retries: 10 26 | 27 | networks: 28 | sample-network: 29 | driver: bridge 30 | -------------------------------------------------------------------------------- /tests/Sample.Tests/Sample.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | all 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Sample.Components/StateMachines/RegistrationState.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.StateMachines; 2 | 3 | using MassTransit; 4 | 5 | 6 | public class RegistrationState : 7 | SagaStateMachineInstance 8 | { 9 | public string? ParticipantEmailAddress { get; set; } 10 | public string? ParticipantLicenseNumber { get; set; } 11 | public string? ParticipantCategory { get; set; } 12 | 13 | public DateTime? ParticipantLicenseExpirationDate { get; set; } 14 | public Guid? RegistrationId { get; set; } 15 | 16 | public string? CardNumber { get; set; } 17 | 18 | public string? EventId { get; set; } 19 | public string? RaceId { get; set; } 20 | 21 | public string? CurrentState { get; set; } 22 | 23 | public string? Reason { get; set; } 24 | 25 | public int? RetryAttempt { get; set; } 26 | public Guid? ScheduleRetryToken { get; set; } 27 | 28 | public Guid CorrelationId { get; set; } 29 | } -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Migrations/20250211032911_Updated2.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace Sample.Api.SqlServer.Migrations 6 | { 7 | /// 8 | public partial class Updated2 : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.AddColumn( 14 | name: "job_properties", 15 | schema: "sample", 16 | table: "job_saga", 17 | type: "nvarchar(max)", 18 | nullable: true); 19 | } 20 | 21 | /// 22 | protected override void Down(MigrationBuilder migrationBuilder) 23 | { 24 | migrationBuilder.DropColumn( 25 | name: "job_properties", 26 | schema: "sample", 27 | table: "job_saga"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Sample.Components/Activities/AssignWaiverActivity.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | using MassTransit; 4 | using Microsoft.Extensions.Logging; 5 | 6 | 7 | public class AssignWaiverActivity : 8 | IExecuteActivity 9 | { 10 | readonly ILogger _logger; 11 | 12 | public AssignWaiverActivity(ILogger logger) 13 | { 14 | _logger = logger; 15 | } 16 | 17 | public async Task Execute(ExecuteContext context) 18 | { 19 | var arguments = context.Arguments; 20 | 21 | var emailAddress = arguments.ParticipantEmailAddress; 22 | 23 | _logger.LogInformation("Assigning waiver to: {Email}", emailAddress); 24 | 25 | await Task.Delay(10); 26 | 27 | if (emailAddress == "joey@friends.tv") 28 | throw new RoutingSlipException($"The document server failed to respond: {emailAddress}"); 29 | 30 | 31 | return context.Completed(); 32 | } 33 | } -------------------------------------------------------------------------------- /src/Sample.Components/StateMachines/RegistrationStateInstanceMap.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.StateMachines; 2 | 3 | using MassTransit; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 6 | 7 | 8 | public class RegistrationStateInstanceMap : 9 | SagaClassMap 10 | { 11 | protected override void Configure(EntityTypeBuilder entity, ModelBuilder model) 12 | { 13 | entity.Property(x => x.ParticipantEmailAddress); 14 | entity.Property(x => x.ParticipantCategory); 15 | entity.Property(x => x.ParticipantLicenseNumber); 16 | entity.Property(x => x.ParticipantLicenseExpirationDate); 17 | entity.Property(x => x.RegistrationId); 18 | entity.Property(x => x.CardNumber); 19 | entity.Property(x => x.EventId); 20 | entity.Property(x => x.RaceId); 21 | entity.Property(x => x.Reason); 22 | entity.Property(x => x.RetryAttempt); 23 | entity.Property(x => x.ScheduleRetryToken); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Sample.Components/CorrelationInitializer.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using System.Runtime.CompilerServices; 4 | using Contracts; 5 | using MassTransit; 6 | 7 | 8 | public static class CorrelationInitializer 9 | { 10 | #pragma warning disable CA2255 11 | [ModuleInitializer] 12 | #pragma warning restore CA2255 13 | public static void Initialize() 14 | { 15 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 16 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 17 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 18 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 19 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 20 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 21 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 22 | MessageCorrelation.UseCorrelationId(x => x.SubmissionId); 23 | MessageCorrelation.UseCorrelationId(x => x.RegistrationId); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Sample.Api.SqlServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Sample.Components/Activities/LicenseVerificationActivity.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | using MassTransit; 4 | using Microsoft.Extensions.Logging; 5 | 6 | 7 | public class LicenseVerificationActivity : 8 | IExecuteActivity 9 | { 10 | readonly ILogger _logger; 11 | 12 | public LicenseVerificationActivity(ILogger logger) 13 | { 14 | _logger = logger; 15 | } 16 | 17 | public async Task Execute(ExecuteContext context) 18 | { 19 | var arguments = context.Arguments; 20 | 21 | var licenseNumber = arguments.ParticipantLicenseNumber; 22 | 23 | _logger.LogInformation("Verifying license: {LicenseNumber} {Category}/{EventType}", licenseNumber, arguments.ParticipantCategory, arguments.EventType); 24 | 25 | await Task.Delay(10); 26 | 27 | if (licenseNumber == "8675309") 28 | throw new RoutingSlipException($"The license number is invalid: {licenseNumber}"); 29 | 30 | DateTime? expirationDate = DateTime.UtcNow.Date + TimeSpan.FromDays(90); 31 | 32 | return context.CompletedWithVariables(new { ParticipantLicenseExpirationDate = expirationDate }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Sample.Api/Sample.Api.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Sample.Components/MigrationHostedService.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using MassTransit; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.Extensions.Logging; 8 | 9 | 10 | public class MigrationHostedService : 11 | IHostedService 12 | where TDbContext : DbContext 13 | { 14 | readonly ILogger> _logger; 15 | readonly IServiceScopeFactory _scopeFactory; 16 | TDbContext? _context; 17 | IServiceScope? _scope; 18 | 19 | public MigrationHostedService(IServiceScopeFactory scopeFactory, ILogger> logger) 20 | { 21 | _scopeFactory = scopeFactory; 22 | _logger = logger; 23 | } 24 | 25 | public async Task StartAsync(CancellationToken cancellationToken) 26 | { 27 | _logger.LogInformation("Applying migrations for {DbContext}", TypeCache.ShortName); 28 | 29 | _scope = _scopeFactory.CreateScope(); 30 | 31 | _context = _scope.ServiceProvider.GetRequiredService(); 32 | 33 | await _context.Database.MigrateAsync(cancellationToken); 34 | } 35 | 36 | public Task StopAsync(CancellationToken cancellationToken) 37 | { 38 | return Task.CompletedTask; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Sample.Components/PartitionKeyExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using Contracts; 4 | using MassTransit; 5 | 6 | 7 | public static class PartitionKeyExtensions 8 | { 9 | public static void ConfigurePartitionKeyFormatters(this IBusFactoryConfigurator cfg) 10 | { 11 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 12 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 13 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 14 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 15 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 16 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 17 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 18 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.RegistrationId.ToString("N")); 19 | cfg.SendTopology.UsePartitionKeyFormatter(p => p.Message.SubmissionId.ToString("N")); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Sample.Api/PgSqlTransportExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Api; 2 | 3 | using MassTransit; 4 | using Npgsql; 5 | 6 | 7 | public static class PgSqlTransportExtensions 8 | { 9 | /// 10 | /// Works some shenanigans to get all the host options configured for the Postgresql transport 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | public static IServiceCollection ConfigurePostgresTransport(this IServiceCollection services, string? connectionString, bool create = true, 18 | bool delete = false) 19 | { 20 | var builder = new NpgsqlConnectionStringBuilder(connectionString); 21 | 22 | services.AddOptions().Configure(options => 23 | { 24 | options.Host = builder.Host ?? "localhost"; 25 | options.Database = builder.Database ?? "sample"; 26 | options.Schema = "transport"; 27 | options.Role = "transport"; 28 | options.Username = "masstransit"; 29 | options.Password = "H4rd2Gu3ss!"; 30 | options.AdminUsername = builder.Username; 31 | options.AdminPassword = builder.Password; 32 | }); 33 | 34 | services.AddPostgresMigrationHostedService(create, delete); 35 | 36 | return services; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/SqlServerTransportExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Api.SqlServer; 2 | 3 | using MassTransit; 4 | using Microsoft.Data.SqlClient; 5 | 6 | 7 | public static class SqlServerTransportExtensions 8 | { 9 | /// 10 | /// Works some shenanigans to get all the host options configured for the SqlServer transport 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | public static IServiceCollection ConfigureSqlServerTransport(this IServiceCollection services, string? connectionString, bool create = true, 18 | bool delete = false) 19 | { 20 | SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); 21 | 22 | services.AddOptions().Configure(options => 23 | { 24 | options.Host = "localhost"; 25 | options.Database = builder.InitialCatalog ?? "sample"; 26 | options.Schema = "transport"; 27 | options.Role = "transport"; 28 | options.Username = "masstransit"; 29 | options.Password = "H4rd2Gu3ss!"; 30 | options.AdminUsername = builder.UserID ?? "sa"; 31 | options.AdminPassword = builder.Password ?? "Password12!"; 32 | }); 33 | 34 | services.AddSqlServerMigrationHostedService(create, delete); 35 | 36 | return services; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Sample.Components/Consumers/SubmitRegistrationConsumer.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Consumers; 2 | 3 | using Contracts; 4 | using MassTransit; 5 | using Microsoft.Extensions.Logging; 6 | 7 | 8 | public class SubmitRegistrationConsumer : 9 | IConsumer 10 | { 11 | readonly ILogger _logger; 12 | 13 | public SubmitRegistrationConsumer(ILogger logger) 14 | { 15 | _logger = logger; 16 | } 17 | 18 | public async Task Consume(ConsumeContext context) 19 | { 20 | _logger.LogInformation("Registration received: {SubmissionId} ({Email})", context.Message.SubmissionId, context.Message.ParticipantEmailAddress); 21 | 22 | ValidateRegistration(context.Message); 23 | 24 | await context.Publish(context.Message); 25 | 26 | _logger.LogInformation("Registration accepted: {SubmissionId} ({Email})", context.Message.SubmissionId, context.Message.ParticipantEmailAddress); 27 | } 28 | 29 | void ValidateRegistration(SubmitRegistration message) 30 | { 31 | if (string.IsNullOrWhiteSpace(message.EventId)) 32 | throw new ArgumentNullException(nameof(message.EventId)); 33 | if (string.IsNullOrWhiteSpace(message.RaceId)) 34 | throw new ArgumentNullException(nameof(message.RaceId)); 35 | 36 | if (string.IsNullOrWhiteSpace(message.ParticipantEmailAddress)) 37 | throw new ArgumentNullException(nameof(message.ParticipantEmailAddress)); 38 | if (string.IsNullOrWhiteSpace(message.ParticipantCategory)) 39 | throw new ArgumentNullException(nameof(message.ParticipantCategory)); 40 | } 41 | } -------------------------------------------------------------------------------- /src/Sample.Components/Activities/ProcessPaymentActivity.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | using MassTransit; 4 | using Microsoft.Extensions.Logging; 5 | 6 | 7 | public class ProcessPaymentActivity : 8 | IActivity 9 | { 10 | readonly ILogger _logger; 11 | 12 | public ProcessPaymentActivity(ILogger logger) 13 | { 14 | _logger = logger; 15 | } 16 | 17 | public async Task Execute(ExecuteContext context) 18 | { 19 | _logger.LogInformation("Processing Payment: {Amount}", context.Arguments.Amount); 20 | 21 | if (context.Arguments.CardNumber == "4147") 22 | throw new RoutingSlipException("The card number is invalid"); 23 | 24 | if (context.Arguments.CardNumber == "187187") 25 | throw new TransientException("The payment provider isn't responding"); 26 | 27 | if (context.Arguments.CardNumber == "187") 28 | { 29 | if (context.GetRetryAttempt() == 0 && context.GetRedeliveryCount() == 0) 30 | throw new TransientException("The payment provider isn't responding"); 31 | 32 | if (context.GetRedeliveryCount() == 0) 33 | throw new LongTransientException("The payment provider isn't responding after a long time"); 34 | } 35 | 36 | await Task.Delay(10); 37 | 38 | const string authorizationCode = "ABC123"; 39 | 40 | return context.Completed(new 41 | { 42 | ChargeDate = DateTime.UtcNow, 43 | authorizationCode, 44 | context.Arguments.Amount, 45 | }); 46 | } 47 | 48 | public async Task Compensate(CompensateContext context) 49 | { 50 | await Task.Delay(10); 51 | 52 | return context.Compensated(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/Sample.Components/SampleDbContext.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components; 2 | 3 | using MassTransit; 4 | using MassTransit.EntityFrameworkCoreIntegration; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.EntityFrameworkCore.Metadata.Internal; 7 | using StateMachines; 8 | 9 | 10 | public class SampleDbContext : 11 | SagaDbContext 12 | { 13 | public SampleDbContext(DbContextOptions options) 14 | : base(options) 15 | { 16 | } 17 | 18 | protected override IEnumerable Configurations 19 | { 20 | get 21 | { 22 | yield return new JobTypeSagaMap(false); 23 | yield return new JobSagaMap(false); 24 | yield return new JobAttemptSagaMap(false); 25 | yield return new RegistrationStateInstanceMap(); 26 | } 27 | } 28 | 29 | protected override void OnModelCreating(ModelBuilder modelBuilder) 30 | { 31 | modelBuilder.HasDefaultSchema("sample"); 32 | 33 | base.OnModelCreating(modelBuilder); 34 | 35 | modelBuilder.AddInboxStateEntity(); 36 | modelBuilder.AddOutboxMessageEntity(); 37 | modelBuilder.AddOutboxStateEntity(); 38 | 39 | foreach (var entity in modelBuilder.Model.GetEntityTypes()) 40 | { 41 | #pragma warning disable EF1001 42 | if (entity is EntityType { IsImplicitlyCreatedJoinEntityType: true }) 43 | continue; 44 | 45 | entity.SetTableName(entity.DisplayName()); 46 | } 47 | 48 | ChangeEntityNames(modelBuilder); 49 | } 50 | 51 | static void ChangeEntityNames(ModelBuilder builder) 52 | { 53 | foreach (var entity in builder.Model.GetEntityTypes()) 54 | { 55 | var tableName = entity.GetTableName(); 56 | if (!string.IsNullOrWhiteSpace(tableName)) 57 | entity.SetTableName(tableName.ToSnakeCase()); 58 | 59 | foreach (var property in entity.GetProperties()) 60 | property.SetColumnName(property.GetColumnName().ToSnakeCase()); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/Sample.Api/Controllers/RegistrationController.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Api.Controllers; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Contracts; 7 | using MassTransit; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | 11 | 12 | [ApiController] 13 | [Route("[controller]")] 14 | public class RegistrationController : 15 | ControllerBase 16 | { 17 | /// 18 | /// Return the registration detail, including status 19 | /// 20 | /// The registration submission id 21 | /// 22 | /// 23 | [HttpGet("{submissionId}", Name = "RegistrationStatus")] 24 | [ProducesResponseType(StatusCodes.Status200OK)] 25 | [ProducesResponseType(StatusCodes.Status404NotFound)] 26 | public async Task Get(Guid submissionId, [FromServices] IRequestClient client) 27 | { 28 | try 29 | { 30 | Response response = await client.GetResponse(new { submissionId }); 31 | 32 | var registration = response.Message; 33 | 34 | return Ok(registration); 35 | } 36 | catch (RequestFaultException ex) 37 | { 38 | return NotFound(ex.Message); 39 | } 40 | } 41 | 42 | /// 43 | /// Submits an order 44 | /// The registration has been accepted but not yet completed 45 | /// 46 | /// The registration detail 47 | /// 48 | /// 49 | [HttpPost] 50 | [ProducesResponseType(StatusCodes.Status202Accepted)] 51 | public async Task Post([FromBody] RegistrationDetail registration, [FromServices] IPublishEndpoint publishEndpoint) 52 | { 53 | await publishEndpoint.Publish(registration); 54 | 55 | var response = new 56 | { 57 | registration.SubmissionId, 58 | Actions = new Dictionary { { "Status", Url.Link("RegistrationStatus", new { submissionId = registration.SubmissionId })! } } 59 | }; 60 | 61 | return Ok(response); 62 | } 63 | } -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Controllers/RegistrationController.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Api.SqlServer.Controllers; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using MassTransit; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Sample.Contracts; 10 | 11 | 12 | [ApiController] 13 | [Route("[controller]")] 14 | public class RegistrationController : 15 | ControllerBase 16 | { 17 | /// 18 | /// Return the registration detail, including status 19 | /// 20 | /// The registration submission id 21 | /// 22 | /// 23 | [HttpGet("{submissionId}", Name = "RegistrationStatus")] 24 | [ProducesResponseType(StatusCodes.Status200OK)] 25 | [ProducesResponseType(StatusCodes.Status404NotFound)] 26 | public async Task Get(Guid submissionId, [FromServices] IRequestClient client) 27 | { 28 | try 29 | { 30 | Response response = await client.GetResponse(new { submissionId }); 31 | 32 | var registration = response.Message; 33 | 34 | return Ok(registration); 35 | } 36 | catch (RequestFaultException ex) 37 | { 38 | return NotFound(ex.Message); 39 | } 40 | } 41 | 42 | /// 43 | /// Submits an order 44 | /// The registration has been accepted but not yet completed 45 | /// 46 | /// The registration detail 47 | /// 48 | /// 49 | [HttpPost] 50 | [ProducesResponseType(StatusCodes.Status202Accepted)] 51 | public async Task Post([FromBody] RegistrationDetail registration, [FromServices] IPublishEndpoint publishEndpoint) 52 | { 53 | await publishEndpoint.Publish(registration); 54 | 55 | var response = new 56 | { 57 | registration.SubmissionId, 58 | Actions = new Dictionary { { "Status", Url.Link("RegistrationStatus", new { submissionId = registration.SubmissionId })! } } 59 | }; 60 | 61 | return Ok(response); 62 | } 63 | } -------------------------------------------------------------------------------- /src/Sample.Components/Activities/EventRegistrationActivity.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Activities; 2 | 3 | using MassTransit; 4 | using Microsoft.Extensions.Logging; 5 | 6 | 7 | public class EventRegistrationActivity : 8 | IActivity 9 | { 10 | readonly ILogger _logger; 11 | readonly IEndpointAddressProvider _provider; 12 | 13 | public EventRegistrationActivity(ILogger logger, IEndpointAddressProvider provider) 14 | { 15 | _logger = logger; 16 | _provider = provider; 17 | } 18 | 19 | public async Task Execute(ExecuteContext context) 20 | { 21 | var arguments = context.Arguments; 22 | 23 | _logger.LogInformation("Registering for event: {EventId} ({Email})", arguments.EventId, arguments.ParticipantEmailAddress); 24 | 25 | var registrationTotal = 25.00m; 26 | 27 | if (!string.IsNullOrWhiteSpace(arguments.ParticipantLicenseNumber)) 28 | { 29 | _logger.LogInformation("Participant Detail: {LicenseNumber} ({LicenseExpiration}) {Category}", 30 | arguments.ParticipantLicenseNumber, arguments.ParticipantLicenseExpirationDate, arguments.ParticipantCategory); 31 | 32 | registrationTotal = 15.0m; 33 | } 34 | 35 | await Task.Delay(10); 36 | 37 | Guid? registrationId = NewId.NextGuid(); 38 | 39 | _logger.LogInformation("Registered for event: {RegistrationId} ({Email})", registrationId, arguments.ParticipantEmailAddress); 40 | 41 | var log = new EventRegistrationLog 42 | { 43 | RegistrationId = registrationId.Value, 44 | ParticipantEmailAddress = arguments.ParticipantEmailAddress 45 | }; 46 | 47 | var variables = new 48 | { 49 | registrationId, 50 | Amount = registrationTotal 51 | }; 52 | 53 | if (arguments.EventId?.StartsWith("DANGER") ?? false) 54 | { 55 | return context.ReviseItinerary(log, variables, x => 56 | { 57 | x.AddActivitiesFromSourceItinerary(); 58 | x.AddActivity("Assign Waiver", _provider.GetExecuteEndpoint()); 59 | }); 60 | } 61 | 62 | return context.CompletedWithVariables(new 63 | { 64 | registrationId, 65 | arguments.ParticipantEmailAddress 66 | }, variables); 67 | } 68 | 69 | public async Task Compensate(CompensateContext context) 70 | { 71 | _logger.LogInformation("Removing registration for event: {RegistrationId} ({Email})", context.Log.RegistrationId, context.Log.ParticipantEmailAddress); 72 | 73 | await Task.Delay(10); 74 | 75 | return context.Compensated(); 76 | } 77 | } -------------------------------------------------------------------------------- /src/Sample.Components/Consumers/ProcessRegistrationConsumer.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.Consumers; 2 | 3 | using Activities; 4 | using Contracts; 5 | using MassTransit; 6 | using MassTransit.Courier.Contracts; 7 | using Microsoft.Extensions.Logging; 8 | using Services; 9 | 10 | 11 | public class ProcessRegistrationConsumer : 12 | IConsumer 13 | { 14 | readonly ILogger _logger; 15 | readonly ISecurePaymentInfoService _paymentInfoService; 16 | readonly IEndpointAddressProvider _provider; 17 | 18 | public ProcessRegistrationConsumer(ILogger logger, IEndpointAddressProvider provider) 19 | { 20 | _logger = logger; 21 | _provider = provider; 22 | _paymentInfoService = new SecurePaymentInfoService(); 23 | } 24 | 25 | public async Task Consume(ConsumeContext context) 26 | { 27 | _logger.LogInformation("Processing registration: {0} ({1})", context.Message.SubmissionId, context.Message.ParticipantEmailAddress); 28 | 29 | var routingSlip = CreateRoutingSlip(context); 30 | 31 | await context.Execute(routingSlip).ConfigureAwait(false); 32 | } 33 | 34 | RoutingSlip CreateRoutingSlip(ConsumeContext context) 35 | { 36 | var builder = new RoutingSlipBuilder(NewId.NextGuid()); 37 | 38 | builder.SetVariables(new 39 | { 40 | context.Message.ParticipantEmailAddress, 41 | context.Message.ParticipantLicenseNumber, 42 | context.Message.ParticipantCategory, 43 | }); 44 | 45 | if (!string.IsNullOrWhiteSpace(context.Message.ParticipantLicenseNumber)) 46 | { 47 | builder.AddActivity("LicenseVerification", _provider.GetExecuteEndpoint(), 48 | new 49 | { 50 | EventType = "Road", 51 | }); 52 | 53 | builder.AddSubscription(context.SourceAddress, RoutingSlipEvents.ActivityFaulted, RoutingSlipEventContents.None, "LicenseVerification", 54 | x => x.Send(new { context.Message.SubmissionId })); 55 | } 56 | 57 | builder.AddActivity("EventRegistration", _provider.GetExecuteEndpoint(), 58 | new 59 | { 60 | context.Message.EventId, 61 | context.Message.RaceId 62 | }); 63 | 64 | var paymentInfo = _paymentInfoService.GetPaymentInfo(context.Message.ParticipantEmailAddress, context.Message.CardNumber); 65 | 66 | builder.AddActivity("ProcessPayment", _provider.GetExecuteEndpoint(), paymentInfo); 67 | 68 | builder.AddSubscription(context.SourceAddress, RoutingSlipEvents.ActivityFaulted, RoutingSlipEventContents.None, "ProcessPayment", 69 | x => x.Send(new { context.Message.SubmissionId })); 70 | 71 | builder.AddSubscription(context.SourceAddress, RoutingSlipEvents.Completed, 72 | x => x.Send(new { context.Message.SubmissionId })); 73 | 74 | return builder.Build(); 75 | } 76 | } -------------------------------------------------------------------------------- /Sample-DbTransport.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31903.59 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5F22C13E-816C-4E25-9385-4B76F43DC1C8}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Api", "src\Sample.Api\Sample.Api.csproj", "{23647B69-5FAF-43E2-A3E0-E60462BAAF1E}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Components", "src\Sample.Components\Sample.Components.csproj", "{69C263F3-57E4-45B3-A264-940F22282E91}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{88C4B3F9-86C6-469D-9DF8-971A284DDC8F}" 13 | ProjectSection(SolutionItems) = preProject 14 | tests\SampleRequests.http = tests\SampleRequests.http 15 | EndProjectSection 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Tests", "tests\Sample.Tests\Sample.Tests.csproj", "{ACD4A11E-58A1-47D9-8D01-E125313E5424}" 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", "{A0044F73-9996-46C7-B199-B534797951F8}" 20 | ProjectSection(SolutionItems) = preProject 21 | docker-compose.yml = docker-compose.yml 22 | README.md = README.md 23 | EndProjectSection 24 | EndProject 25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Contracts", "src\Sample.Contracts\Sample.Contracts.csproj", "{C5371417-AC26-420B-A0C7-9B6C6B81ECBF}" 26 | EndProject 27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Api.SqlServer", "src\Sample.Api.SqlServer\Sample.Api.SqlServer.csproj", "{04181B99-3952-4906-9855-A03C7D4E9118}" 28 | EndProject 29 | Global 30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 31 | Debug|Any CPU = Debug|Any CPU 32 | Release|Any CPU = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 38 | {23647B69-5FAF-43E2-A3E0-E60462BAAF1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {23647B69-5FAF-43E2-A3E0-E60462BAAF1E}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {23647B69-5FAF-43E2-A3E0-E60462BAAF1E}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {23647B69-5FAF-43E2-A3E0-E60462BAAF1E}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {69C263F3-57E4-45B3-A264-940F22282E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {69C263F3-57E4-45B3-A264-940F22282E91}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {69C263F3-57E4-45B3-A264-940F22282E91}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {69C263F3-57E4-45B3-A264-940F22282E91}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {ACD4A11E-58A1-47D9-8D01-E125313E5424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {ACD4A11E-58A1-47D9-8D01-E125313E5424}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {ACD4A11E-58A1-47D9-8D01-E125313E5424}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {ACD4A11E-58A1-47D9-8D01-E125313E5424}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {C5371417-AC26-420B-A0C7-9B6C6B81ECBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {C5371417-AC26-420B-A0C7-9B6C6B81ECBF}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {C5371417-AC26-420B-A0C7-9B6C6B81ECBF}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {C5371417-AC26-420B-A0C7-9B6C6B81ECBF}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {04181B99-3952-4906-9855-A03C7D4E9118}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {04181B99-3952-4906-9855-A03C7D4E9118}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {04181B99-3952-4906-9855-A03C7D4E9118}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {04181B99-3952-4906-9855-A03C7D4E9118}.Release|Any CPU.Build.0 = Release|Any CPU 58 | EndGlobalSection 59 | GlobalSection(NestedProjects) = preSolution 60 | {23647B69-5FAF-43E2-A3E0-E60462BAAF1E} = {5F22C13E-816C-4E25-9385-4B76F43DC1C8} 61 | {69C263F3-57E4-45B3-A264-940F22282E91} = {5F22C13E-816C-4E25-9385-4B76F43DC1C8} 62 | {ACD4A11E-58A1-47D9-8D01-E125313E5424} = {88C4B3F9-86C6-469D-9DF8-971A284DDC8F} 63 | {C5371417-AC26-420B-A0C7-9B6C6B81ECBF} = {5F22C13E-816C-4E25-9385-4B76F43DC1C8} 64 | {04181B99-3952-4906-9855-A03C7D4E9118} = {5F22C13E-816C-4E25-9385-4B76F43DC1C8} 65 | EndGlobalSection 66 | EndGlobal 67 | -------------------------------------------------------------------------------- /src/Sample.Api/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using MassTransit; 3 | using Microsoft.AspNetCore.Diagnostics.HealthChecks; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Diagnostics.HealthChecks; 6 | using NSwag; 7 | using Sample.Api; 8 | using Sample.Components; 9 | using Serilog; 10 | using Serilog.Events; 11 | using Serilog.Sinks.SystemConsole.Themes; 12 | 13 | Log.Logger = new LoggerConfiguration() 14 | .MinimumLevel.Information() 15 | .MinimumLevel.Override("MassTransit", LogEventLevel.Debug) 16 | .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) 17 | .MinimumLevel.Override("Microsoft.Hosting", LogEventLevel.Information) 18 | .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) 19 | .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning) 20 | .Enrich.FromLogContext() 21 | .WriteTo.Console(theme: AnsiConsoleTheme.Code) 22 | .CreateLogger(); 23 | 24 | var builder = WebApplication.CreateBuilder(args); 25 | 26 | builder.Host.UseSerilog(); 27 | 28 | var connectionString = builder.Configuration.GetConnectionString("Db"); 29 | 30 | builder.Services.AddDbContext(x => 31 | { 32 | x.UseNpgsql(connectionString, options => 33 | { 34 | options.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name); 35 | options.MigrationsHistoryTable("ef_migration_history"); 36 | }); 37 | }); 38 | builder.Services.AddHostedService>(); 39 | 40 | 41 | builder.Services.AddSingleton(); 42 | 43 | builder.Services.ConfigurePostgresTransport(connectionString); 44 | builder.Services.AddMassTransit(x => 45 | { 46 | x.AddSqlMessageScheduler(); 47 | 48 | x.SetEntityFrameworkSagaRepositoryProvider(r => 49 | { 50 | r.ExistingDbContext(); 51 | r.UsePostgres(); 52 | }); 53 | 54 | x.AddJobSagaStateMachines() 55 | .EntityFrameworkRepository(r => 56 | { 57 | r.ExistingDbContext(); 58 | r.UsePostgres(); 59 | }); 60 | 61 | x.SetKebabCaseEndpointNameFormatter(); 62 | 63 | x.AddEntityFrameworkOutbox(o => 64 | { 65 | o.UsePostgres(); 66 | }); 67 | 68 | x.AddConfigureEndpointsCallback((context, _, cfg) => 69 | { 70 | cfg.UseDelayedRedelivery(r => 71 | { 72 | r.Handle(); 73 | r.Interval(10000, 15000); 74 | }); 75 | 76 | cfg.UseMessageRetry(r => 77 | { 78 | r.Handle(); 79 | r.Interval(25, 50); 80 | }); 81 | 82 | if (cfg is ISqlReceiveEndpointConfigurator sql) 83 | sql.SetReceiveMode(SqlReceiveMode.Partitioned); 84 | 85 | cfg.UseEntityFrameworkOutbox(context); 86 | }); 87 | 88 | x.AddConsumersFromNamespaceContaining(); 89 | x.AddActivitiesFromNamespaceContaining(); 90 | x.AddSagaStateMachinesFromNamespaceContaining(); 91 | 92 | x.UsingPostgres((context, cfg) => 93 | { 94 | cfg.UseSqlMessageScheduler(); 95 | 96 | cfg.UseJobSagaPartitionKeyFormatters(); 97 | cfg.ConfigurePartitionKeyFormatters(); 98 | 99 | cfg.AutoStart = true; 100 | 101 | cfg.ConfigureEndpoints(context); 102 | }); 103 | }); 104 | 105 | builder.Services.AddOptions() 106 | .Configure(options => 107 | { 108 | options.WaitUntilStarted = true; 109 | options.StartTimeout = TimeSpan.FromSeconds(10); 110 | options.StopTimeout = TimeSpan.FromSeconds(30); 111 | options.ConsumerStopTimeout = TimeSpan.FromSeconds(10); 112 | }); 113 | builder.Services.AddOptions() 114 | .Configure(options => options.ShutdownTimeout = TimeSpan.FromMinutes(1)); 115 | 116 | builder.Services.AddControllers(); 117 | 118 | builder.Services.AddEndpointsApiExplorer(); 119 | builder.Services.AddOpenApiDocument(cfg => cfg.PostProcess = d => 120 | { 121 | d.Info.Title = "MassTransit Database Transport Sample"; 122 | d.Info.Contact = new OpenApiContact 123 | { 124 | Name = "MassTransit Support", 125 | Email = "support@masstransit.io" 126 | }; 127 | }); 128 | 129 | var app = builder.Build(); 130 | 131 | if (app.Environment.IsDevelopment()) 132 | { 133 | app.UseOpenApi(); 134 | app.UseSwaggerUi(); 135 | } 136 | 137 | app.UseRouting(); 138 | app.MapControllers(); 139 | 140 | static Task HealthCheckResponseWriter(HttpContext context, HealthReport result) 141 | { 142 | context.Response.ContentType = "application/json"; 143 | 144 | return context.Response.WriteAsync(result.ToJsonString()); 145 | } 146 | 147 | app.MapHealthChecks("/health/ready", new HealthCheckOptions 148 | { 149 | Predicate = check => check.Tags.Contains("ready"), 150 | ResponseWriter = HealthCheckResponseWriter 151 | }); 152 | 153 | app.MapHealthChecks("/health/live", new HealthCheckOptions { ResponseWriter = HealthCheckResponseWriter }); 154 | 155 | app.Run(); -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using MassTransit; 3 | using Microsoft.AspNetCore.Diagnostics.HealthChecks; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.Extensions.Diagnostics.HealthChecks; 6 | using NSwag; 7 | using Sample.Api.SqlServer; 8 | using Sample.Components; 9 | using Serilog; 10 | using Serilog.Events; 11 | using Serilog.Sinks.SystemConsole.Themes; 12 | 13 | Log.Logger = new LoggerConfiguration() 14 | .MinimumLevel.Information() 15 | .MinimumLevel.Override("MassTransit", LogEventLevel.Debug) 16 | .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) 17 | .MinimumLevel.Override("Microsoft.Hosting", LogEventLevel.Information) 18 | .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) 19 | .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning) 20 | .Enrich.FromLogContext() 21 | .WriteTo.Console(theme: AnsiConsoleTheme.Code) 22 | .CreateLogger(); 23 | 24 | var builder = WebApplication.CreateBuilder(args); 25 | 26 | builder.Host.UseSerilog(); 27 | 28 | var connectionString = builder.Configuration.GetConnectionString("Db"); 29 | 30 | builder.Services.AddDbContext(x => 31 | { 32 | x.UseSqlServer(connectionString, options => 33 | { 34 | options.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name); 35 | options.MigrationsHistoryTable("ef_migration_history"); 36 | }); 37 | }); 38 | builder.Services.AddHostedService>(); 39 | 40 | 41 | builder.Services.AddSingleton(); 42 | 43 | builder.Services.ConfigureSqlServerTransport(connectionString); 44 | builder.Services.AddMassTransit(x => 45 | { 46 | x.AddSqlMessageScheduler(); 47 | 48 | x.SetEntityFrameworkSagaRepositoryProvider(r => 49 | { 50 | r.ExistingDbContext(); 51 | r.UseSqlServer(); 52 | }); 53 | 54 | x.AddJobSagaStateMachines() 55 | .EntityFrameworkRepository(r => 56 | { 57 | r.ExistingDbContext(); 58 | r.UseSqlServer(); 59 | }); 60 | 61 | x.SetKebabCaseEndpointNameFormatter(); 62 | 63 | x.AddEntityFrameworkOutbox(o => 64 | { 65 | o.UseSqlServer(); 66 | }); 67 | 68 | x.AddConfigureEndpointsCallback((context, _, cfg) => 69 | { 70 | cfg.UseDelayedRedelivery(r => 71 | { 72 | r.Handle(); 73 | r.Interval(10000, 15000); 74 | }); 75 | 76 | cfg.UseMessageRetry(r => 77 | { 78 | r.Handle(); 79 | r.Interval(25, 50); 80 | }); 81 | 82 | if (cfg is ISqlReceiveEndpointConfigurator sql) 83 | sql.SetReceiveMode(SqlReceiveMode.Partitioned); 84 | 85 | cfg.UseEntityFrameworkOutbox(context); 86 | }); 87 | 88 | x.AddConsumersFromNamespaceContaining(); 89 | x.AddActivitiesFromNamespaceContaining(); 90 | x.AddSagaStateMachinesFromNamespaceContaining(); 91 | 92 | x.UsingSqlServer((context, cfg) => 93 | { 94 | cfg.UseSqlMessageScheduler(); 95 | 96 | cfg.UseJobSagaPartitionKeyFormatters(); 97 | cfg.ConfigurePartitionKeyFormatters(); 98 | 99 | cfg.AutoStart = true; 100 | 101 | cfg.ConfigureEndpoints(context); 102 | }); 103 | }); 104 | 105 | builder.Services.AddOptions() 106 | .Configure(options => 107 | { 108 | options.WaitUntilStarted = true; 109 | options.StartTimeout = TimeSpan.FromSeconds(10); 110 | options.StopTimeout = TimeSpan.FromSeconds(30); 111 | options.ConsumerStopTimeout = TimeSpan.FromSeconds(10); 112 | }); 113 | builder.Services.AddOptions() 114 | .Configure(options => options.ShutdownTimeout = TimeSpan.FromMinutes(1)); 115 | 116 | builder.Services.AddControllers(); 117 | 118 | builder.Services.AddEndpointsApiExplorer(); 119 | builder.Services.AddOpenApiDocument(cfg => cfg.PostProcess = d => 120 | { 121 | d.Info.Title = "MassTransit Database Transport Sample"; 122 | d.Info.Contact = new OpenApiContact 123 | { 124 | Name = "MassTransit Support", 125 | Email = "support@masstransit.io" 126 | }; 127 | }); 128 | 129 | var app = builder.Build(); 130 | 131 | if (app.Environment.IsDevelopment()) 132 | { 133 | app.UseOpenApi(); 134 | app.UseSwaggerUi(); 135 | } 136 | 137 | app.UseRouting(); 138 | app.MapControllers(); 139 | 140 | static Task HealthCheckResponseWriter(HttpContext context, HealthReport result) 141 | { 142 | context.Response.ContentType = "application/json"; 143 | 144 | return context.Response.WriteAsync(result.ToJsonString()); 145 | } 146 | 147 | app.MapHealthChecks("/health/ready", new HealthCheckOptions 148 | { 149 | Predicate = check => check.Tags.Contains("ready"), 150 | ResponseWriter = HealthCheckResponseWriter 151 | }); 152 | 153 | app.MapHealthChecks("/health/live", new HealthCheckOptions { ResponseWriter = HealthCheckResponseWriter }); 154 | 155 | app.Run(); -------------------------------------------------------------------------------- /src/Sample.Components/StateMachines/RegistrationStateMachine.cs: -------------------------------------------------------------------------------- 1 | namespace Sample.Components.StateMachines; 2 | 3 | using Contracts; 4 | using MassTransit; 5 | 6 | 7 | public class RegistrationStateMachine : 8 | MassTransitStateMachine 9 | { 10 | public RegistrationStateMachine() 11 | { 12 | InstanceState(x => x.CurrentState); 13 | 14 | Event(() => RegistrationStatusRequested, x => 15 | { 16 | x.ReadOnly = true; 17 | x.OnMissingInstance(m => m.Fault()); 18 | }); 19 | 20 | Schedule(() => RetryDelayExpired, saga => saga.ScheduleRetryToken, x => 21 | { 22 | x.Received = r => 23 | { 24 | r.CorrelateById(context => context.Message.RegistrationId); 25 | r.ConfigureConsumeTopology = false; 26 | }; 27 | }); 28 | 29 | Initially( 30 | When(EventRegistrationReceived) 31 | .Initialize() 32 | .InitiateProcessing() 33 | .TransitionTo(Received)); 34 | 35 | During(Received, 36 | When(EventRegistrationCompleted) 37 | .Registered() 38 | .TransitionTo(Registered), 39 | When(LicenseVerificationFailed) 40 | .InvalidLicense() 41 | .TransitionTo(Suspended), 42 | When(PaymentFailed) 43 | .PaymentFailed() 44 | .TransitionTo(Suspended)); 45 | 46 | During(Suspended, 47 | When(EventRegistrationReceived) 48 | .Initialize() 49 | .InitiateProcessing() 50 | .TransitionTo(Received)); 51 | 52 | During(WaitingToRetry, 53 | When(RetryDelayExpired.Received) 54 | .RetryProcessing() 55 | .TransitionTo(Received)); 56 | 57 | DuringAny( 58 | When(RegistrationStatusRequested) 59 | .RespondAsync(x => x.Init(new 60 | { 61 | SubmissionId = x.Saga.CorrelationId, 62 | x.Saga.ParticipantEmailAddress, 63 | x.Saga.ParticipantLicenseNumber, 64 | x.Saga.ParticipantLicenseExpirationDate, 65 | x.Saga.RegistrationId, 66 | x.Saga.EventId, 67 | x.Saga.RaceId, 68 | Status = x.Saga.CurrentState 69 | }) 70 | )); 71 | 72 | // could easily be configured via options 73 | const int retryCount = 5; 74 | var retryDelay = TimeSpan.FromSeconds(10); 75 | 76 | WhenEnter(Suspended, x => x 77 | .If(context => context.Saga.RetryAttempt < retryCount, 78 | retry => retry 79 | .Schedule(RetryDelayExpired, context => new RetryDelayExpired(context.Saga.CorrelationId), _ => retryDelay) 80 | .TransitionTo(WaitingToRetry) 81 | ) 82 | ); 83 | } 84 | 85 | // 86 | // ReSharper disable UnassignedGetOnlyAutoProperty 87 | // ReSharper disable MemberCanBePrivate.Global 88 | public State Received { get; } = null!; 89 | public State Registered { get; } = null!; 90 | public State WaitingToRetry { get; } = null!; 91 | public State Suspended { get; } = null!; 92 | 93 | public Event EventRegistrationReceived { get; } = null!; 94 | public Event RegistrationStatusRequested { get; } = null!; 95 | public Event EventRegistrationCompleted { get; } = null!; 96 | public Event LicenseVerificationFailed { get; } = null!; 97 | public Event PaymentFailed { get; } = null!; 98 | 99 | public Schedule RetryDelayExpired { get; } = null!; 100 | } 101 | 102 | 103 | static class RegistrationStateMachineBehaviorExtensions 104 | { 105 | public static EventActivityBinder Initialize( 106 | this EventActivityBinder binder) 107 | { 108 | return binder.Then(context => 109 | { 110 | context.Saga.ParticipantEmailAddress = context.Message.ParticipantEmailAddress; 111 | context.Saga.ParticipantLicenseNumber = context.Message.ParticipantLicenseNumber; 112 | context.Saga.ParticipantCategory = context.Message.ParticipantCategory; 113 | 114 | context.Saga.EventId = context.Message.EventId; 115 | context.Saga.RaceId = context.Message.RaceId; 116 | 117 | LogContext.Info?.Log("Processing: {0} ({1})", context.Message.SubmissionId, context.Message.ParticipantEmailAddress); 118 | }); 119 | } 120 | 121 | public static EventActivityBinder InitiateProcessing( 122 | this EventActivityBinder binder) 123 | { 124 | return binder.PublishAsync(context => context.Init(context.Message)); 125 | } 126 | 127 | public static EventActivityBinder RetryProcessing( 128 | this EventActivityBinder binder) 129 | { 130 | return binder 131 | .Then(context => context.Saga.RetryAttempt++) 132 | .PublishAsync(context => context.Init(new 133 | { 134 | SubmissionId = context.Saga.CorrelationId, 135 | context.Saga.ParticipantEmailAddress, 136 | context.Saga.ParticipantLicenseNumber, 137 | context.Saga.ParticipantCategory, 138 | context.Saga.CardNumber, 139 | context.Saga.EventId, 140 | context.Saga.RaceId, 141 | __Header_Registration_RetryAttempt = context.Saga.RetryAttempt 142 | })); 143 | } 144 | 145 | public static EventActivityBinder Registered( 146 | this EventActivityBinder binder) 147 | { 148 | return binder.Then(context => 149 | { 150 | LogContext.Info?.Log("Registered: {0} ({1})", context.Message.SubmissionId, context.Saga.ParticipantEmailAddress); 151 | 152 | context.Saga.ParticipantLicenseExpirationDate = context.GetVariable("ParticipantLicenseExpirationDate"); 153 | context.Saga.RegistrationId = context.GetVariable("RegistrationId"); 154 | }); 155 | } 156 | 157 | public static EventActivityBinder InvalidLicense( 158 | this EventActivityBinder binder) 159 | { 160 | return binder.Then(context => 161 | { 162 | LogContext.Info?.Log("Invalid License: {0} ({1}) - {2}", context.Message.SubmissionId, context.Saga.ParticipantLicenseNumber, 163 | context.Message.ExceptionInfo?.Message); 164 | 165 | context.Saga.Reason = "Invalid License"; 166 | }); 167 | } 168 | 169 | public static EventActivityBinder PaymentFailed( 170 | this EventActivityBinder binder) 171 | { 172 | return binder.Then(context => 173 | { 174 | LogContext.Info?.Log("Payment Failed: {0} ({1}) - {2}", context.Message.SubmissionId, context.Saga.ParticipantEmailAddress, 175 | context.Message.ExceptionInfo?.Message); 176 | 177 | context.Saga.Reason = "Payment Failed"; 178 | }); 179 | } 180 | } -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Migrations/20241004184901_Updated.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace Sample.Api.SqlServer.Migrations 7 | { 8 | /// 9 | public partial class Updated : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.AddColumn( 15 | name: "global_concurrent_job_limit", 16 | schema: "sample", 17 | table: "job_type_saga", 18 | type: "int", 19 | nullable: true); 20 | 21 | migrationBuilder.AddColumn( 22 | name: "properties", 23 | schema: "sample", 24 | table: "job_type_saga", 25 | type: "nvarchar(max)", 26 | nullable: true); 27 | 28 | migrationBuilder.AddColumn( 29 | name: "cron_expression", 30 | schema: "sample", 31 | table: "job_saga", 32 | type: "nvarchar(max)", 33 | nullable: true); 34 | 35 | migrationBuilder.AddColumn( 36 | name: "end_date", 37 | schema: "sample", 38 | table: "job_saga", 39 | type: "datetimeoffset", 40 | nullable: true); 41 | 42 | migrationBuilder.AddColumn( 43 | name: "incomplete_attempts", 44 | schema: "sample", 45 | table: "job_saga", 46 | type: "nvarchar(max)", 47 | nullable: true); 48 | 49 | migrationBuilder.AddColumn( 50 | name: "job_state", 51 | schema: "sample", 52 | table: "job_saga", 53 | type: "nvarchar(max)", 54 | nullable: true); 55 | 56 | migrationBuilder.AddColumn( 57 | name: "last_progress_limit", 58 | schema: "sample", 59 | table: "job_saga", 60 | type: "bigint", 61 | nullable: true); 62 | 63 | migrationBuilder.AddColumn( 64 | name: "last_progress_sequence_number", 65 | schema: "sample", 66 | table: "job_saga", 67 | type: "bigint", 68 | nullable: true); 69 | 70 | migrationBuilder.AddColumn( 71 | name: "last_progress_value", 72 | schema: "sample", 73 | table: "job_saga", 74 | type: "bigint", 75 | nullable: true); 76 | 77 | migrationBuilder.AddColumn( 78 | name: "next_start_date", 79 | schema: "sample", 80 | table: "job_saga", 81 | type: "datetimeoffset", 82 | nullable: true); 83 | 84 | migrationBuilder.AddColumn( 85 | name: "start_date", 86 | schema: "sample", 87 | table: "job_saga", 88 | type: "datetimeoffset", 89 | nullable: true); 90 | 91 | migrationBuilder.AddColumn( 92 | name: "time_zone_id", 93 | schema: "sample", 94 | table: "job_saga", 95 | type: "nvarchar(max)", 96 | nullable: true); 97 | 98 | migrationBuilder.AddForeignKey( 99 | name: "FK_job_attempt_saga_job_saga_job_id", 100 | schema: "sample", 101 | table: "job_attempt_saga", 102 | column: "job_id", 103 | principalSchema: "sample", 104 | principalTable: "job_saga", 105 | principalColumn: "correlation_id", 106 | onDelete: ReferentialAction.Cascade); 107 | 108 | migrationBuilder.AddForeignKey( 109 | name: "FK_outbox_message_inbox_state_inbox_message_id_inbox_consumer_id", 110 | schema: "sample", 111 | table: "outbox_message", 112 | columns: new[] { "inbox_message_id", "inbox_consumer_id" }, 113 | principalSchema: "sample", 114 | principalTable: "inbox_state", 115 | principalColumns: new[] { "message_id", "consumer_id" }); 116 | 117 | migrationBuilder.AddForeignKey( 118 | name: "FK_outbox_message_outbox_state_outbox_id", 119 | schema: "sample", 120 | table: "outbox_message", 121 | column: "outbox_id", 122 | principalSchema: "sample", 123 | principalTable: "outbox_state", 124 | principalColumn: "outbox_id"); 125 | } 126 | 127 | /// 128 | protected override void Down(MigrationBuilder migrationBuilder) 129 | { 130 | migrationBuilder.DropForeignKey( 131 | name: "FK_job_attempt_saga_job_saga_job_id", 132 | schema: "sample", 133 | table: "job_attempt_saga"); 134 | 135 | migrationBuilder.DropForeignKey( 136 | name: "FK_outbox_message_inbox_state_inbox_message_id_inbox_consumer_id", 137 | schema: "sample", 138 | table: "outbox_message"); 139 | 140 | migrationBuilder.DropForeignKey( 141 | name: "FK_outbox_message_outbox_state_outbox_id", 142 | schema: "sample", 143 | table: "outbox_message"); 144 | 145 | migrationBuilder.DropColumn( 146 | name: "global_concurrent_job_limit", 147 | schema: "sample", 148 | table: "job_type_saga"); 149 | 150 | migrationBuilder.DropColumn( 151 | name: "properties", 152 | schema: "sample", 153 | table: "job_type_saga"); 154 | 155 | migrationBuilder.DropColumn( 156 | name: "cron_expression", 157 | schema: "sample", 158 | table: "job_saga"); 159 | 160 | migrationBuilder.DropColumn( 161 | name: "end_date", 162 | schema: "sample", 163 | table: "job_saga"); 164 | 165 | migrationBuilder.DropColumn( 166 | name: "incomplete_attempts", 167 | schema: "sample", 168 | table: "job_saga"); 169 | 170 | migrationBuilder.DropColumn( 171 | name: "job_state", 172 | schema: "sample", 173 | table: "job_saga"); 174 | 175 | migrationBuilder.DropColumn( 176 | name: "last_progress_limit", 177 | schema: "sample", 178 | table: "job_saga"); 179 | 180 | migrationBuilder.DropColumn( 181 | name: "last_progress_sequence_number", 182 | schema: "sample", 183 | table: "job_saga"); 184 | 185 | migrationBuilder.DropColumn( 186 | name: "last_progress_value", 187 | schema: "sample", 188 | table: "job_saga"); 189 | 190 | migrationBuilder.DropColumn( 191 | name: "next_start_date", 192 | schema: "sample", 193 | table: "job_saga"); 194 | 195 | migrationBuilder.DropColumn( 196 | name: "start_date", 197 | schema: "sample", 198 | table: "job_saga"); 199 | 200 | migrationBuilder.DropColumn( 201 | name: "time_zone_id", 202 | schema: "sample", 203 | table: "job_saga"); 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/Sample.Api/Migrations/20241004184848_Updated.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace Sample.Api.Migrations 7 | { 8 | /// 9 | public partial class Updated : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.AddColumn( 15 | name: "global_concurrent_job_limit", 16 | schema: "sample", 17 | table: "job_type_saga", 18 | type: "integer", 19 | nullable: true); 20 | 21 | migrationBuilder.AddColumn( 22 | name: "name", 23 | schema: "sample", 24 | table: "job_type_saga", 25 | type: "text", 26 | nullable: true); 27 | 28 | migrationBuilder.AddColumn( 29 | name: "properties", 30 | schema: "sample", 31 | table: "job_type_saga", 32 | type: "text", 33 | nullable: true); 34 | 35 | migrationBuilder.AddColumn( 36 | name: "cron_expression", 37 | schema: "sample", 38 | table: "job_saga", 39 | type: "text", 40 | nullable: true); 41 | 42 | migrationBuilder.AddColumn( 43 | name: "end_date", 44 | schema: "sample", 45 | table: "job_saga", 46 | type: "timestamp with time zone", 47 | nullable: true); 48 | 49 | migrationBuilder.AddColumn( 50 | name: "incomplete_attempts", 51 | schema: "sample", 52 | table: "job_saga", 53 | type: "text", 54 | nullable: true); 55 | 56 | migrationBuilder.AddColumn( 57 | name: "job_state", 58 | schema: "sample", 59 | table: "job_saga", 60 | type: "text", 61 | nullable: true); 62 | 63 | migrationBuilder.AddColumn( 64 | name: "last_progress_limit", 65 | schema: "sample", 66 | table: "job_saga", 67 | type: "bigint", 68 | nullable: true); 69 | 70 | migrationBuilder.AddColumn( 71 | name: "last_progress_sequence_number", 72 | schema: "sample", 73 | table: "job_saga", 74 | type: "bigint", 75 | nullable: true); 76 | 77 | migrationBuilder.AddColumn( 78 | name: "last_progress_value", 79 | schema: "sample", 80 | table: "job_saga", 81 | type: "bigint", 82 | nullable: true); 83 | 84 | migrationBuilder.AddColumn( 85 | name: "next_start_date", 86 | schema: "sample", 87 | table: "job_saga", 88 | type: "timestamp with time zone", 89 | nullable: true); 90 | 91 | migrationBuilder.AddColumn( 92 | name: "start_date", 93 | schema: "sample", 94 | table: "job_saga", 95 | type: "timestamp with time zone", 96 | nullable: true); 97 | 98 | migrationBuilder.AddColumn( 99 | name: "time_zone_id", 100 | schema: "sample", 101 | table: "job_saga", 102 | type: "text", 103 | nullable: true); 104 | 105 | migrationBuilder.AddForeignKey( 106 | name: "FK_job_attempt_saga_job_saga_job_id", 107 | schema: "sample", 108 | table: "job_attempt_saga", 109 | column: "job_id", 110 | principalSchema: "sample", 111 | principalTable: "job_saga", 112 | principalColumn: "correlation_id", 113 | onDelete: ReferentialAction.Cascade); 114 | 115 | migrationBuilder.AddForeignKey( 116 | name: "FK_outbox_message_inbox_state_inbox_message_id_inbox_consumer_~", 117 | schema: "sample", 118 | table: "outbox_message", 119 | columns: new[] { "inbox_message_id", "inbox_consumer_id" }, 120 | principalSchema: "sample", 121 | principalTable: "inbox_state", 122 | principalColumns: new[] { "message_id", "consumer_id" }); 123 | 124 | migrationBuilder.AddForeignKey( 125 | name: "FK_outbox_message_outbox_state_outbox_id", 126 | schema: "sample", 127 | table: "outbox_message", 128 | column: "outbox_id", 129 | principalSchema: "sample", 130 | principalTable: "outbox_state", 131 | principalColumn: "outbox_id"); 132 | } 133 | 134 | /// 135 | protected override void Down(MigrationBuilder migrationBuilder) 136 | { 137 | migrationBuilder.DropForeignKey( 138 | name: "FK_job_attempt_saga_job_saga_job_id", 139 | schema: "sample", 140 | table: "job_attempt_saga"); 141 | 142 | migrationBuilder.DropForeignKey( 143 | name: "FK_outbox_message_inbox_state_inbox_message_id_inbox_consumer_~", 144 | schema: "sample", 145 | table: "outbox_message"); 146 | 147 | migrationBuilder.DropForeignKey( 148 | name: "FK_outbox_message_outbox_state_outbox_id", 149 | schema: "sample", 150 | table: "outbox_message"); 151 | 152 | migrationBuilder.DropColumn( 153 | name: "global_concurrent_job_limit", 154 | schema: "sample", 155 | table: "job_type_saga"); 156 | 157 | migrationBuilder.DropColumn( 158 | name: "name", 159 | schema: "sample", 160 | table: "job_type_saga"); 161 | 162 | migrationBuilder.DropColumn( 163 | name: "properties", 164 | schema: "sample", 165 | table: "job_type_saga"); 166 | 167 | migrationBuilder.DropColumn( 168 | name: "cron_expression", 169 | schema: "sample", 170 | table: "job_saga"); 171 | 172 | migrationBuilder.DropColumn( 173 | name: "end_date", 174 | schema: "sample", 175 | table: "job_saga"); 176 | 177 | migrationBuilder.DropColumn( 178 | name: "incomplete_attempts", 179 | schema: "sample", 180 | table: "job_saga"); 181 | 182 | migrationBuilder.DropColumn( 183 | name: "job_state", 184 | schema: "sample", 185 | table: "job_saga"); 186 | 187 | migrationBuilder.DropColumn( 188 | name: "last_progress_limit", 189 | schema: "sample", 190 | table: "job_saga"); 191 | 192 | migrationBuilder.DropColumn( 193 | name: "last_progress_sequence_number", 194 | schema: "sample", 195 | table: "job_saga"); 196 | 197 | migrationBuilder.DropColumn( 198 | name: "last_progress_value", 199 | schema: "sample", 200 | table: "job_saga"); 201 | 202 | migrationBuilder.DropColumn( 203 | name: "next_start_date", 204 | schema: "sample", 205 | table: "job_saga"); 206 | 207 | migrationBuilder.DropColumn( 208 | name: "start_date", 209 | schema: "sample", 210 | table: "job_saga"); 211 | 212 | migrationBuilder.DropColumn( 213 | name: "time_zone_id", 214 | schema: "sample", 215 | table: "job_saga"); 216 | } 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /src/Sample.Api/Migrations/20230706011449_Initial.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 4 | 5 | #nullable disable 6 | 7 | namespace Sample.Api.Migrations 8 | { 9 | /// 10 | public partial class Initial : Migration 11 | { 12 | /// 13 | protected override void Up(MigrationBuilder migrationBuilder) 14 | { 15 | migrationBuilder.EnsureSchema( 16 | name: "sample"); 17 | 18 | migrationBuilder.CreateTable( 19 | name: "inbox_state", 20 | schema: "sample", 21 | columns: table => new 22 | { 23 | id = table.Column(type: "bigint", nullable: false) 24 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 25 | message_id = table.Column(type: "uuid", nullable: false), 26 | consumer_id = table.Column(type: "uuid", nullable: false), 27 | lock_id = table.Column(type: "uuid", nullable: false), 28 | row_version = table.Column(type: "bytea", rowVersion: true, nullable: true), 29 | received = table.Column(type: "timestamp with time zone", nullable: false), 30 | receive_count = table.Column(type: "integer", nullable: false), 31 | expiration_time = table.Column(type: "timestamp with time zone", nullable: true), 32 | consumed = table.Column(type: "timestamp with time zone", nullable: true), 33 | delivered = table.Column(type: "timestamp with time zone", nullable: true), 34 | last_sequence_number = table.Column(type: "bigint", nullable: true) 35 | }, 36 | constraints: table => 37 | { 38 | table.PrimaryKey("PK_inbox_state", x => x.id); 39 | table.UniqueConstraint("AK_inbox_state_message_id_consumer_id", x => new { x.message_id, x.consumer_id }); 40 | }); 41 | 42 | migrationBuilder.CreateTable( 43 | name: "job_attempt_saga", 44 | schema: "sample", 45 | columns: table => new 46 | { 47 | correlation_id = table.Column(type: "uuid", nullable: false), 48 | current_state = table.Column(type: "integer", nullable: false), 49 | job_id = table.Column(type: "uuid", nullable: false), 50 | retry_attempt = table.Column(type: "integer", nullable: false), 51 | service_address = table.Column(type: "text", nullable: true), 52 | instance_address = table.Column(type: "text", nullable: true), 53 | started = table.Column(type: "timestamp with time zone", nullable: true), 54 | faulted = table.Column(type: "timestamp with time zone", nullable: true), 55 | status_check_token_id = table.Column(type: "uuid", nullable: true) 56 | }, 57 | constraints: table => 58 | { 59 | table.PrimaryKey("PK_job_attempt_saga", x => x.correlation_id); 60 | }); 61 | 62 | migrationBuilder.CreateTable( 63 | name: "job_saga", 64 | schema: "sample", 65 | columns: table => new 66 | { 67 | correlation_id = table.Column(type: "uuid", nullable: false), 68 | current_state = table.Column(type: "integer", nullable: false), 69 | submitted = table.Column(type: "timestamp with time zone", nullable: true), 70 | service_address = table.Column(type: "text", nullable: true), 71 | job_timeout = table.Column(type: "interval", nullable: true), 72 | job = table.Column(type: "text", nullable: true), 73 | job_type_id = table.Column(type: "uuid", nullable: false), 74 | attempt_id = table.Column(type: "uuid", nullable: false), 75 | retry_attempt = table.Column(type: "integer", nullable: false), 76 | started = table.Column(type: "timestamp with time zone", nullable: true), 77 | completed = table.Column(type: "timestamp with time zone", nullable: true), 78 | duration = table.Column(type: "interval", nullable: true), 79 | faulted = table.Column(type: "timestamp with time zone", nullable: true), 80 | reason = table.Column(type: "text", nullable: true), 81 | job_slot_wait_token = table.Column(type: "uuid", nullable: true), 82 | job_retry_delay_token = table.Column(type: "uuid", nullable: true) 83 | }, 84 | constraints: table => 85 | { 86 | table.PrimaryKey("PK_job_saga", x => x.correlation_id); 87 | }); 88 | 89 | migrationBuilder.CreateTable( 90 | name: "job_type_saga", 91 | schema: "sample", 92 | columns: table => new 93 | { 94 | correlation_id = table.Column(type: "uuid", nullable: false), 95 | current_state = table.Column(type: "integer", nullable: false), 96 | active_job_count = table.Column(type: "integer", nullable: false), 97 | concurrent_job_limit = table.Column(type: "integer", nullable: false), 98 | override_job_limit = table.Column(type: "integer", nullable: true), 99 | override_limit_expiration = table.Column(type: "timestamp with time zone", nullable: true), 100 | active_jobs = table.Column(type: "text", nullable: true), 101 | instances = table.Column(type: "text", nullable: true) 102 | }, 103 | constraints: table => 104 | { 105 | table.PrimaryKey("PK_job_type_saga", x => x.correlation_id); 106 | }); 107 | 108 | migrationBuilder.CreateTable( 109 | name: "outbox_message", 110 | schema: "sample", 111 | columns: table => new 112 | { 113 | sequence_number = table.Column(type: "bigint", nullable: false) 114 | .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), 115 | enqueue_time = table.Column(type: "timestamp with time zone", nullable: true), 116 | sent_time = table.Column(type: "timestamp with time zone", nullable: false), 117 | headers = table.Column(type: "text", nullable: true), 118 | properties = table.Column(type: "text", nullable: true), 119 | inbox_message_id = table.Column(type: "uuid", nullable: true), 120 | inbox_consumer_id = table.Column(type: "uuid", nullable: true), 121 | outbox_id = table.Column(type: "uuid", nullable: true), 122 | message_id = table.Column(type: "uuid", nullable: false), 123 | content_type = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), 124 | message_type = table.Column(type: "text", nullable: false), 125 | body = table.Column(type: "text", nullable: false), 126 | conversation_id = table.Column(type: "uuid", nullable: true), 127 | correlation_id = table.Column(type: "uuid", nullable: true), 128 | initiator_id = table.Column(type: "uuid", nullable: true), 129 | request_id = table.Column(type: "uuid", nullable: true), 130 | source_address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), 131 | destination_address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), 132 | response_address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), 133 | fault_address = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), 134 | expiration_time = table.Column(type: "timestamp with time zone", nullable: true) 135 | }, 136 | constraints: table => 137 | { 138 | table.PrimaryKey("PK_outbox_message", x => x.sequence_number); 139 | }); 140 | 141 | migrationBuilder.CreateTable( 142 | name: "outbox_state", 143 | schema: "sample", 144 | columns: table => new 145 | { 146 | outbox_id = table.Column(type: "uuid", nullable: false), 147 | lock_id = table.Column(type: "uuid", nullable: false), 148 | row_version = table.Column(type: "bytea", rowVersion: true, nullable: true), 149 | created = table.Column(type: "timestamp with time zone", nullable: false), 150 | delivered = table.Column(type: "timestamp with time zone", nullable: true), 151 | last_sequence_number = table.Column(type: "bigint", nullable: true) 152 | }, 153 | constraints: table => 154 | { 155 | table.PrimaryKey("PK_outbox_state", x => x.outbox_id); 156 | }); 157 | 158 | migrationBuilder.CreateTable( 159 | name: "registration_state", 160 | schema: "sample", 161 | columns: table => new 162 | { 163 | correlation_id = table.Column(type: "uuid", nullable: false), 164 | participant_email_address = table.Column(type: "text", nullable: true), 165 | participant_license_number = table.Column(type: "text", nullable: true), 166 | participant_category = table.Column(type: "text", nullable: true), 167 | participant_license_expiration_date = table.Column(type: "timestamp with time zone", nullable: true), 168 | registration_id = table.Column(type: "uuid", nullable: true), 169 | card_number = table.Column(type: "text", nullable: true), 170 | event_id = table.Column(type: "text", nullable: true), 171 | race_id = table.Column(type: "text", nullable: true), 172 | current_state = table.Column(type: "text", nullable: true), 173 | reason = table.Column(type: "text", nullable: true), 174 | retry_attempt = table.Column(type: "integer", nullable: true), 175 | schedule_retry_token = table.Column(type: "uuid", nullable: true) 176 | }, 177 | constraints: table => 178 | { 179 | table.PrimaryKey("PK_registration_state", x => x.correlation_id); 180 | }); 181 | 182 | migrationBuilder.CreateIndex( 183 | name: "IX_inbox_state_delivered", 184 | schema: "sample", 185 | table: "inbox_state", 186 | column: "delivered"); 187 | 188 | migrationBuilder.CreateIndex( 189 | name: "IX_job_attempt_saga_job_id_retry_attempt", 190 | schema: "sample", 191 | table: "job_attempt_saga", 192 | columns: new[] { "job_id", "retry_attempt" }, 193 | unique: true); 194 | 195 | migrationBuilder.CreateIndex( 196 | name: "IX_outbox_message_enqueue_time", 197 | schema: "sample", 198 | table: "outbox_message", 199 | column: "enqueue_time"); 200 | 201 | migrationBuilder.CreateIndex( 202 | name: "IX_outbox_message_expiration_time", 203 | schema: "sample", 204 | table: "outbox_message", 205 | column: "expiration_time"); 206 | 207 | migrationBuilder.CreateIndex( 208 | name: "IX_outbox_message_inbox_message_id_inbox_consumer_id_sequence_~", 209 | schema: "sample", 210 | table: "outbox_message", 211 | columns: new[] { "inbox_message_id", "inbox_consumer_id", "sequence_number" }, 212 | unique: true); 213 | 214 | migrationBuilder.CreateIndex( 215 | name: "IX_outbox_message_outbox_id_sequence_number", 216 | schema: "sample", 217 | table: "outbox_message", 218 | columns: new[] { "outbox_id", "sequence_number" }, 219 | unique: true); 220 | 221 | migrationBuilder.CreateIndex( 222 | name: "IX_outbox_state_created", 223 | schema: "sample", 224 | table: "outbox_state", 225 | column: "created"); 226 | } 227 | 228 | /// 229 | protected override void Down(MigrationBuilder migrationBuilder) 230 | { 231 | migrationBuilder.DropTable( 232 | name: "inbox_state", 233 | schema: "sample"); 234 | 235 | migrationBuilder.DropTable( 236 | name: "job_attempt_saga", 237 | schema: "sample"); 238 | 239 | migrationBuilder.DropTable( 240 | name: "job_saga", 241 | schema: "sample"); 242 | 243 | migrationBuilder.DropTable( 244 | name: "job_type_saga", 245 | schema: "sample"); 246 | 247 | migrationBuilder.DropTable( 248 | name: "outbox_message", 249 | schema: "sample"); 250 | 251 | migrationBuilder.DropTable( 252 | name: "outbox_state", 253 | schema: "sample"); 254 | 255 | migrationBuilder.DropTable( 256 | name: "registration_state", 257 | schema: "sample"); 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Migrations/20230815145325_InitialSqlServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace Sample.Api.SqlServer.Migrations 7 | { 8 | /// 9 | public partial class InitialSqlServer : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.EnsureSchema( 15 | name: "sample"); 16 | 17 | migrationBuilder.CreateTable( 18 | name: "inbox_state", 19 | schema: "sample", 20 | columns: table => new 21 | { 22 | id = table.Column(type: "bigint", nullable: false) 23 | .Annotation("SqlServer:Identity", "1, 1"), 24 | message_id = table.Column(type: "uniqueidentifier", nullable: false), 25 | consumer_id = table.Column(type: "uniqueidentifier", nullable: false), 26 | lock_id = table.Column(type: "uniqueidentifier", nullable: false), 27 | row_version = table.Column(type: "rowversion", rowVersion: true, nullable: true), 28 | received = table.Column(type: "datetime2", nullable: false), 29 | receive_count = table.Column(type: "int", nullable: false), 30 | expiration_time = table.Column(type: "datetime2", nullable: true), 31 | consumed = table.Column(type: "datetime2", nullable: true), 32 | delivered = table.Column(type: "datetime2", nullable: true), 33 | last_sequence_number = table.Column(type: "bigint", nullable: true) 34 | }, 35 | constraints: table => 36 | { 37 | table.PrimaryKey("PK_inbox_state", x => x.id); 38 | table.UniqueConstraint("AK_inbox_state_message_id_consumer_id", x => new { x.message_id, x.consumer_id }); 39 | }); 40 | 41 | migrationBuilder.CreateTable( 42 | name: "job_attempt_saga", 43 | schema: "sample", 44 | columns: table => new 45 | { 46 | correlation_id = table.Column(type: "uniqueidentifier", nullable: false), 47 | current_state = table.Column(type: "int", nullable: false), 48 | job_id = table.Column(type: "uniqueidentifier", nullable: false), 49 | retry_attempt = table.Column(type: "int", nullable: false), 50 | service_address = table.Column(type: "nvarchar(max)", nullable: true), 51 | instance_address = table.Column(type: "nvarchar(max)", nullable: true), 52 | started = table.Column(type: "datetime2", nullable: true), 53 | faulted = table.Column(type: "datetime2", nullable: true), 54 | status_check_token_id = table.Column(type: "uniqueidentifier", nullable: true) 55 | }, 56 | constraints: table => 57 | { 58 | table.PrimaryKey("PK_job_attempt_saga", x => x.correlation_id); 59 | }); 60 | 61 | migrationBuilder.CreateTable( 62 | name: "job_saga", 63 | schema: "sample", 64 | columns: table => new 65 | { 66 | correlation_id = table.Column(type: "uniqueidentifier", nullable: false), 67 | current_state = table.Column(type: "int", nullable: false), 68 | submitted = table.Column(type: "datetime2", nullable: true), 69 | service_address = table.Column(type: "nvarchar(max)", nullable: true), 70 | job_timeout = table.Column(type: "time", nullable: true), 71 | job = table.Column(type: "nvarchar(max)", nullable: true), 72 | job_type_id = table.Column(type: "uniqueidentifier", nullable: false), 73 | attempt_id = table.Column(type: "uniqueidentifier", nullable: false), 74 | retry_attempt = table.Column(type: "int", nullable: false), 75 | started = table.Column(type: "datetime2", nullable: true), 76 | completed = table.Column(type: "datetime2", nullable: true), 77 | duration = table.Column(type: "time", nullable: true), 78 | faulted = table.Column(type: "datetime2", nullable: true), 79 | reason = table.Column(type: "nvarchar(max)", nullable: true), 80 | job_slot_wait_token = table.Column(type: "uniqueidentifier", nullable: true), 81 | job_retry_delay_token = table.Column(type: "uniqueidentifier", nullable: true) 82 | }, 83 | constraints: table => 84 | { 85 | table.PrimaryKey("PK_job_saga", x => x.correlation_id); 86 | }); 87 | 88 | migrationBuilder.CreateTable( 89 | name: "job_type_saga", 90 | schema: "sample", 91 | columns: table => new 92 | { 93 | correlation_id = table.Column(type: "uniqueidentifier", nullable: false), 94 | current_state = table.Column(type: "int", nullable: false), 95 | active_job_count = table.Column(type: "int", nullable: false), 96 | concurrent_job_limit = table.Column(type: "int", nullable: false), 97 | name = table.Column(type: "nvarchar(max)", nullable: true), 98 | override_job_limit = table.Column(type: "int", nullable: true), 99 | override_limit_expiration = table.Column(type: "datetime2", nullable: true), 100 | active_jobs = table.Column(type: "nvarchar(max)", nullable: true), 101 | instances = table.Column(type: "nvarchar(max)", nullable: true) 102 | }, 103 | constraints: table => 104 | { 105 | table.PrimaryKey("PK_job_type_saga", x => x.correlation_id); 106 | }); 107 | 108 | migrationBuilder.CreateTable( 109 | name: "outbox_message", 110 | schema: "sample", 111 | columns: table => new 112 | { 113 | sequence_number = table.Column(type: "bigint", nullable: false) 114 | .Annotation("SqlServer:Identity", "1, 1"), 115 | enqueue_time = table.Column(type: "datetime2", nullable: true), 116 | sent_time = table.Column(type: "datetime2", nullable: false), 117 | headers = table.Column(type: "nvarchar(max)", nullable: true), 118 | properties = table.Column(type: "nvarchar(max)", nullable: true), 119 | inbox_message_id = table.Column(type: "uniqueidentifier", nullable: true), 120 | inbox_consumer_id = table.Column(type: "uniqueidentifier", nullable: true), 121 | outbox_id = table.Column(type: "uniqueidentifier", nullable: true), 122 | message_id = table.Column(type: "uniqueidentifier", nullable: false), 123 | content_type = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), 124 | message_type = table.Column(type: "nvarchar(max)", nullable: false), 125 | body = table.Column(type: "nvarchar(max)", nullable: false), 126 | conversation_id = table.Column(type: "uniqueidentifier", nullable: true), 127 | correlation_id = table.Column(type: "uniqueidentifier", nullable: true), 128 | initiator_id = table.Column(type: "uniqueidentifier", nullable: true), 129 | request_id = table.Column(type: "uniqueidentifier", nullable: true), 130 | source_address = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 131 | destination_address = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 132 | response_address = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 133 | fault_address = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 134 | expiration_time = table.Column(type: "datetime2", nullable: true) 135 | }, 136 | constraints: table => 137 | { 138 | table.PrimaryKey("PK_outbox_message", x => x.sequence_number); 139 | }); 140 | 141 | migrationBuilder.CreateTable( 142 | name: "outbox_state", 143 | schema: "sample", 144 | columns: table => new 145 | { 146 | outbox_id = table.Column(type: "uniqueidentifier", nullable: false), 147 | lock_id = table.Column(type: "uniqueidentifier", nullable: false), 148 | row_version = table.Column(type: "rowversion", rowVersion: true, nullable: true), 149 | created = table.Column(type: "datetime2", nullable: false), 150 | delivered = table.Column(type: "datetime2", nullable: true), 151 | last_sequence_number = table.Column(type: "bigint", nullable: true) 152 | }, 153 | constraints: table => 154 | { 155 | table.PrimaryKey("PK_outbox_state", x => x.outbox_id); 156 | }); 157 | 158 | migrationBuilder.CreateTable( 159 | name: "registration_state", 160 | schema: "sample", 161 | columns: table => new 162 | { 163 | correlation_id = table.Column(type: "uniqueidentifier", nullable: false), 164 | participant_email_address = table.Column(type: "nvarchar(max)", nullable: true), 165 | participant_license_number = table.Column(type: "nvarchar(max)", nullable: true), 166 | participant_category = table.Column(type: "nvarchar(max)", nullable: true), 167 | participant_license_expiration_date = table.Column(type: "datetime2", nullable: true), 168 | registration_id = table.Column(type: "uniqueidentifier", nullable: true), 169 | card_number = table.Column(type: "nvarchar(max)", nullable: true), 170 | event_id = table.Column(type: "nvarchar(max)", nullable: true), 171 | race_id = table.Column(type: "nvarchar(max)", nullable: true), 172 | current_state = table.Column(type: "nvarchar(max)", nullable: true), 173 | reason = table.Column(type: "nvarchar(max)", nullable: true), 174 | retry_attempt = table.Column(type: "int", nullable: true), 175 | schedule_retry_token = table.Column(type: "uniqueidentifier", nullable: true) 176 | }, 177 | constraints: table => 178 | { 179 | table.PrimaryKey("PK_registration_state", x => x.correlation_id); 180 | }); 181 | 182 | migrationBuilder.CreateIndex( 183 | name: "IX_inbox_state_delivered", 184 | schema: "sample", 185 | table: "inbox_state", 186 | column: "delivered"); 187 | 188 | migrationBuilder.CreateIndex( 189 | name: "IX_job_attempt_saga_job_id_retry_attempt", 190 | schema: "sample", 191 | table: "job_attempt_saga", 192 | columns: new[] { "job_id", "retry_attempt" }, 193 | unique: true); 194 | 195 | migrationBuilder.CreateIndex( 196 | name: "IX_outbox_message_enqueue_time", 197 | schema: "sample", 198 | table: "outbox_message", 199 | column: "enqueue_time"); 200 | 201 | migrationBuilder.CreateIndex( 202 | name: "IX_outbox_message_expiration_time", 203 | schema: "sample", 204 | table: "outbox_message", 205 | column: "expiration_time"); 206 | 207 | migrationBuilder.CreateIndex( 208 | name: "IX_outbox_message_inbox_message_id_inbox_consumer_id_sequence_number", 209 | schema: "sample", 210 | table: "outbox_message", 211 | columns: new[] { "inbox_message_id", "inbox_consumer_id", "sequence_number" }, 212 | unique: true, 213 | filter: "[inbox_message_id] IS NOT NULL AND [inbox_consumer_id] IS NOT NULL"); 214 | 215 | migrationBuilder.CreateIndex( 216 | name: "IX_outbox_message_outbox_id_sequence_number", 217 | schema: "sample", 218 | table: "outbox_message", 219 | columns: new[] { "outbox_id", "sequence_number" }, 220 | unique: true, 221 | filter: "[outbox_id] IS NOT NULL"); 222 | 223 | migrationBuilder.CreateIndex( 224 | name: "IX_outbox_state_created", 225 | schema: "sample", 226 | table: "outbox_state", 227 | column: "created"); 228 | } 229 | 230 | /// 231 | protected override void Down(MigrationBuilder migrationBuilder) 232 | { 233 | migrationBuilder.DropTable( 234 | name: "inbox_state", 235 | schema: "sample"); 236 | 237 | migrationBuilder.DropTable( 238 | name: "job_attempt_saga", 239 | schema: "sample"); 240 | 241 | migrationBuilder.DropTable( 242 | name: "job_saga", 243 | schema: "sample"); 244 | 245 | migrationBuilder.DropTable( 246 | name: "job_type_saga", 247 | schema: "sample"); 248 | 249 | migrationBuilder.DropTable( 250 | name: "outbox_message", 251 | schema: "sample"); 252 | 253 | migrationBuilder.DropTable( 254 | name: "outbox_state", 255 | schema: "sample"); 256 | 257 | migrationBuilder.DropTable( 258 | name: "registration_state", 259 | schema: "sample"); 260 | } 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/Sample.Api/Migrations/20230706011449_Initial.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 8 | using Sample.Components; 9 | 10 | #nullable disable 11 | 12 | namespace Sample.Api.Migrations 13 | { 14 | [DbContext(typeof(SampleDbContext))] 15 | [Migration("20230706011449_Initial")] 16 | partial class Initial 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasDefaultSchema("sample") 24 | .HasAnnotation("ProductVersion", "7.0.5") 25 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 26 | 27 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 28 | 29 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => 30 | { 31 | b.Property("Id") 32 | .ValueGeneratedOnAdd() 33 | .HasColumnType("bigint") 34 | .HasColumnName("id"); 35 | 36 | NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); 37 | 38 | b.Property("Consumed") 39 | .HasColumnType("timestamp with time zone") 40 | .HasColumnName("consumed"); 41 | 42 | b.Property("ConsumerId") 43 | .HasColumnType("uuid") 44 | .HasColumnName("consumer_id"); 45 | 46 | b.Property("Delivered") 47 | .HasColumnType("timestamp with time zone") 48 | .HasColumnName("delivered"); 49 | 50 | b.Property("ExpirationTime") 51 | .HasColumnType("timestamp with time zone") 52 | .HasColumnName("expiration_time"); 53 | 54 | b.Property("LastSequenceNumber") 55 | .HasColumnType("bigint") 56 | .HasColumnName("last_sequence_number"); 57 | 58 | b.Property("LockId") 59 | .HasColumnType("uuid") 60 | .HasColumnName("lock_id"); 61 | 62 | b.Property("MessageId") 63 | .HasColumnType("uuid") 64 | .HasColumnName("message_id"); 65 | 66 | b.Property("ReceiveCount") 67 | .HasColumnType("integer") 68 | .HasColumnName("receive_count"); 69 | 70 | b.Property("Received") 71 | .HasColumnType("timestamp with time zone") 72 | .HasColumnName("received"); 73 | 74 | b.Property("RowVersion") 75 | .IsConcurrencyToken() 76 | .ValueGeneratedOnAddOrUpdate() 77 | .HasColumnType("bytea") 78 | .HasColumnName("row_version"); 79 | 80 | b.HasKey("Id"); 81 | 82 | b.HasAlternateKey("MessageId", "ConsumerId"); 83 | 84 | b.HasIndex("Delivered"); 85 | 86 | b.ToTable("inbox_state", "sample"); 87 | }); 88 | 89 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 90 | { 91 | b.Property("SequenceNumber") 92 | .ValueGeneratedOnAdd() 93 | .HasColumnType("bigint") 94 | .HasColumnName("sequence_number"); 95 | 96 | NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); 97 | 98 | b.Property("Body") 99 | .IsRequired() 100 | .HasColumnType("text") 101 | .HasColumnName("body"); 102 | 103 | b.Property("ContentType") 104 | .IsRequired() 105 | .HasMaxLength(256) 106 | .HasColumnType("character varying(256)") 107 | .HasColumnName("content_type"); 108 | 109 | b.Property("ConversationId") 110 | .HasColumnType("uuid") 111 | .HasColumnName("conversation_id"); 112 | 113 | b.Property("CorrelationId") 114 | .HasColumnType("uuid") 115 | .HasColumnName("correlation_id"); 116 | 117 | b.Property("DestinationAddress") 118 | .HasMaxLength(256) 119 | .HasColumnType("character varying(256)") 120 | .HasColumnName("destination_address"); 121 | 122 | b.Property("EnqueueTime") 123 | .HasColumnType("timestamp with time zone") 124 | .HasColumnName("enqueue_time"); 125 | 126 | b.Property("ExpirationTime") 127 | .HasColumnType("timestamp with time zone") 128 | .HasColumnName("expiration_time"); 129 | 130 | b.Property("FaultAddress") 131 | .HasMaxLength(256) 132 | .HasColumnType("character varying(256)") 133 | .HasColumnName("fault_address"); 134 | 135 | b.Property("Headers") 136 | .HasColumnType("text") 137 | .HasColumnName("headers"); 138 | 139 | b.Property("InboxConsumerId") 140 | .HasColumnType("uuid") 141 | .HasColumnName("inbox_consumer_id"); 142 | 143 | b.Property("InboxMessageId") 144 | .HasColumnType("uuid") 145 | .HasColumnName("inbox_message_id"); 146 | 147 | b.Property("InitiatorId") 148 | .HasColumnType("uuid") 149 | .HasColumnName("initiator_id"); 150 | 151 | b.Property("MessageId") 152 | .HasColumnType("uuid") 153 | .HasColumnName("message_id"); 154 | 155 | b.Property("MessageType") 156 | .IsRequired() 157 | .HasColumnType("text") 158 | .HasColumnName("message_type"); 159 | 160 | b.Property("OutboxId") 161 | .HasColumnType("uuid") 162 | .HasColumnName("outbox_id"); 163 | 164 | b.Property("Properties") 165 | .HasColumnType("text") 166 | .HasColumnName("properties"); 167 | 168 | b.Property("RequestId") 169 | .HasColumnType("uuid") 170 | .HasColumnName("request_id"); 171 | 172 | b.Property("ResponseAddress") 173 | .HasMaxLength(256) 174 | .HasColumnType("character varying(256)") 175 | .HasColumnName("response_address"); 176 | 177 | b.Property("SentTime") 178 | .HasColumnType("timestamp with time zone") 179 | .HasColumnName("sent_time"); 180 | 181 | b.Property("SourceAddress") 182 | .HasMaxLength(256) 183 | .HasColumnType("character varying(256)") 184 | .HasColumnName("source_address"); 185 | 186 | b.HasKey("SequenceNumber"); 187 | 188 | b.HasIndex("EnqueueTime"); 189 | 190 | b.HasIndex("ExpirationTime"); 191 | 192 | b.HasIndex("OutboxId", "SequenceNumber") 193 | .IsUnique(); 194 | 195 | b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") 196 | .IsUnique(); 197 | 198 | b.ToTable("outbox_message", "sample"); 199 | }); 200 | 201 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => 202 | { 203 | b.Property("OutboxId") 204 | .ValueGeneratedOnAdd() 205 | .HasColumnType("uuid") 206 | .HasColumnName("outbox_id"); 207 | 208 | b.Property("Created") 209 | .HasColumnType("timestamp with time zone") 210 | .HasColumnName("created"); 211 | 212 | b.Property("Delivered") 213 | .HasColumnType("timestamp with time zone") 214 | .HasColumnName("delivered"); 215 | 216 | b.Property("LastSequenceNumber") 217 | .HasColumnType("bigint") 218 | .HasColumnName("last_sequence_number"); 219 | 220 | b.Property("LockId") 221 | .HasColumnType("uuid") 222 | .HasColumnName("lock_id"); 223 | 224 | b.Property("RowVersion") 225 | .IsConcurrencyToken() 226 | .ValueGeneratedOnAddOrUpdate() 227 | .HasColumnType("bytea") 228 | .HasColumnName("row_version"); 229 | 230 | b.HasKey("OutboxId"); 231 | 232 | b.HasIndex("Created"); 233 | 234 | b.ToTable("outbox_state", "sample"); 235 | }); 236 | 237 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 238 | { 239 | b.Property("CorrelationId") 240 | .HasColumnType("uuid") 241 | .HasColumnName("correlation_id"); 242 | 243 | b.Property("CurrentState") 244 | .HasColumnType("integer") 245 | .HasColumnName("current_state"); 246 | 247 | b.Property("Faulted") 248 | .HasColumnType("timestamp with time zone") 249 | .HasColumnName("faulted"); 250 | 251 | b.Property("InstanceAddress") 252 | .HasColumnType("text") 253 | .HasColumnName("instance_address"); 254 | 255 | b.Property("JobId") 256 | .HasColumnType("uuid") 257 | .HasColumnName("job_id"); 258 | 259 | b.Property("RetryAttempt") 260 | .HasColumnType("integer") 261 | .HasColumnName("retry_attempt"); 262 | 263 | b.Property("ServiceAddress") 264 | .HasColumnType("text") 265 | .HasColumnName("service_address"); 266 | 267 | b.Property("Started") 268 | .HasColumnType("timestamp with time zone") 269 | .HasColumnName("started"); 270 | 271 | b.Property("StatusCheckTokenId") 272 | .HasColumnType("uuid") 273 | .HasColumnName("status_check_token_id"); 274 | 275 | b.HasKey("CorrelationId"); 276 | 277 | b.HasIndex("JobId", "RetryAttempt") 278 | .IsUnique(); 279 | 280 | b.ToTable("job_attempt_saga", "sample"); 281 | }); 282 | 283 | modelBuilder.Entity("MassTransit.JobSaga", b => 284 | { 285 | b.Property("CorrelationId") 286 | .HasColumnType("uuid") 287 | .HasColumnName("correlation_id"); 288 | 289 | b.Property("AttemptId") 290 | .HasColumnType("uuid") 291 | .HasColumnName("attempt_id"); 292 | 293 | b.Property("Completed") 294 | .HasColumnType("timestamp with time zone") 295 | .HasColumnName("completed"); 296 | 297 | b.Property("CurrentState") 298 | .HasColumnType("integer") 299 | .HasColumnName("current_state"); 300 | 301 | b.Property("Duration") 302 | .HasColumnType("interval") 303 | .HasColumnName("duration"); 304 | 305 | b.Property("Faulted") 306 | .HasColumnType("timestamp with time zone") 307 | .HasColumnName("faulted"); 308 | 309 | b.Property("Job") 310 | .HasColumnType("text") 311 | .HasColumnName("job"); 312 | 313 | b.Property("JobRetryDelayToken") 314 | .HasColumnType("uuid") 315 | .HasColumnName("job_retry_delay_token"); 316 | 317 | b.Property("JobSlotWaitToken") 318 | .HasColumnType("uuid") 319 | .HasColumnName("job_slot_wait_token"); 320 | 321 | b.Property("JobTimeout") 322 | .HasColumnType("interval") 323 | .HasColumnName("job_timeout"); 324 | 325 | b.Property("JobTypeId") 326 | .HasColumnType("uuid") 327 | .HasColumnName("job_type_id"); 328 | 329 | b.Property("Reason") 330 | .HasColumnType("text") 331 | .HasColumnName("reason"); 332 | 333 | b.Property("RetryAttempt") 334 | .HasColumnType("integer") 335 | .HasColumnName("retry_attempt"); 336 | 337 | b.Property("ServiceAddress") 338 | .HasColumnType("text") 339 | .HasColumnName("service_address"); 340 | 341 | b.Property("Started") 342 | .HasColumnType("timestamp with time zone") 343 | .HasColumnName("started"); 344 | 345 | b.Property("Submitted") 346 | .HasColumnType("timestamp with time zone") 347 | .HasColumnName("submitted"); 348 | 349 | b.HasKey("CorrelationId"); 350 | 351 | b.ToTable("job_saga", "sample"); 352 | }); 353 | 354 | modelBuilder.Entity("MassTransit.JobTypeSaga", b => 355 | { 356 | b.Property("CorrelationId") 357 | .HasColumnType("uuid") 358 | .HasColumnName("correlation_id"); 359 | 360 | b.Property("ActiveJobCount") 361 | .HasColumnType("integer") 362 | .HasColumnName("active_job_count"); 363 | 364 | b.Property("ActiveJobs") 365 | .HasColumnType("text") 366 | .HasColumnName("active_jobs"); 367 | 368 | b.Property("ConcurrentJobLimit") 369 | .HasColumnType("integer") 370 | .HasColumnName("concurrent_job_limit"); 371 | 372 | b.Property("CurrentState") 373 | .HasColumnType("integer") 374 | .HasColumnName("current_state"); 375 | 376 | b.Property("Instances") 377 | .HasColumnType("text") 378 | .HasColumnName("instances"); 379 | 380 | b.Property("OverrideJobLimit") 381 | .HasColumnType("integer") 382 | .HasColumnName("override_job_limit"); 383 | 384 | b.Property("OverrideLimitExpiration") 385 | .HasColumnType("timestamp with time zone") 386 | .HasColumnName("override_limit_expiration"); 387 | 388 | b.HasKey("CorrelationId"); 389 | 390 | b.ToTable("job_type_saga", "sample"); 391 | }); 392 | 393 | modelBuilder.Entity("Sample.Components.StateMachines.RegistrationState", b => 394 | { 395 | b.Property("CorrelationId") 396 | .HasColumnType("uuid") 397 | .HasColumnName("correlation_id"); 398 | 399 | b.Property("CardNumber") 400 | .HasColumnType("text") 401 | .HasColumnName("card_number"); 402 | 403 | b.Property("CurrentState") 404 | .HasColumnType("text") 405 | .HasColumnName("current_state"); 406 | 407 | b.Property("EventId") 408 | .HasColumnType("text") 409 | .HasColumnName("event_id"); 410 | 411 | b.Property("ParticipantCategory") 412 | .HasColumnType("text") 413 | .HasColumnName("participant_category"); 414 | 415 | b.Property("ParticipantEmailAddress") 416 | .HasColumnType("text") 417 | .HasColumnName("participant_email_address"); 418 | 419 | b.Property("ParticipantLicenseExpirationDate") 420 | .HasColumnType("timestamp with time zone") 421 | .HasColumnName("participant_license_expiration_date"); 422 | 423 | b.Property("ParticipantLicenseNumber") 424 | .HasColumnType("text") 425 | .HasColumnName("participant_license_number"); 426 | 427 | b.Property("RaceId") 428 | .HasColumnType("text") 429 | .HasColumnName("race_id"); 430 | 431 | b.Property("Reason") 432 | .HasColumnType("text") 433 | .HasColumnName("reason"); 434 | 435 | b.Property("RegistrationId") 436 | .HasColumnType("uuid") 437 | .HasColumnName("registration_id"); 438 | 439 | b.Property("RetryAttempt") 440 | .HasColumnType("integer") 441 | .HasColumnName("retry_attempt"); 442 | 443 | b.Property("ScheduleRetryToken") 444 | .HasColumnType("uuid") 445 | .HasColumnName("schedule_retry_token"); 446 | 447 | b.HasKey("CorrelationId"); 448 | 449 | b.ToTable("registration_state", "sample"); 450 | }); 451 | #pragma warning restore 612, 618 452 | } 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Migrations/20230815145325_InitialSqlServer.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Sample.Components; 9 | 10 | #nullable disable 11 | 12 | namespace Sample.Api.SqlServer.Migrations 13 | { 14 | [DbContext(typeof(SampleDbContext))] 15 | [Migration("20230815145325_InitialSqlServer")] 16 | partial class InitialSqlServer 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasDefaultSchema("sample") 24 | .HasAnnotation("ProductVersion", "7.0.5") 25 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 26 | 27 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 28 | 29 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => 30 | { 31 | b.Property("Id") 32 | .ValueGeneratedOnAdd() 33 | .HasColumnType("bigint") 34 | .HasColumnName("id"); 35 | 36 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 37 | 38 | b.Property("Consumed") 39 | .HasColumnType("datetime2") 40 | .HasColumnName("consumed"); 41 | 42 | b.Property("ConsumerId") 43 | .HasColumnType("uniqueidentifier") 44 | .HasColumnName("consumer_id"); 45 | 46 | b.Property("Delivered") 47 | .HasColumnType("datetime2") 48 | .HasColumnName("delivered"); 49 | 50 | b.Property("ExpirationTime") 51 | .HasColumnType("datetime2") 52 | .HasColumnName("expiration_time"); 53 | 54 | b.Property("LastSequenceNumber") 55 | .HasColumnType("bigint") 56 | .HasColumnName("last_sequence_number"); 57 | 58 | b.Property("LockId") 59 | .HasColumnType("uniqueidentifier") 60 | .HasColumnName("lock_id"); 61 | 62 | b.Property("MessageId") 63 | .HasColumnType("uniqueidentifier") 64 | .HasColumnName("message_id"); 65 | 66 | b.Property("ReceiveCount") 67 | .HasColumnType("int") 68 | .HasColumnName("receive_count"); 69 | 70 | b.Property("Received") 71 | .HasColumnType("datetime2") 72 | .HasColumnName("received"); 73 | 74 | b.Property("RowVersion") 75 | .IsConcurrencyToken() 76 | .ValueGeneratedOnAddOrUpdate() 77 | .HasColumnType("rowversion") 78 | .HasColumnName("row_version"); 79 | 80 | b.HasKey("Id"); 81 | 82 | b.HasAlternateKey("MessageId", "ConsumerId"); 83 | 84 | b.HasIndex("Delivered"); 85 | 86 | b.ToTable("inbox_state", "sample"); 87 | }); 88 | 89 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 90 | { 91 | b.Property("SequenceNumber") 92 | .ValueGeneratedOnAdd() 93 | .HasColumnType("bigint") 94 | .HasColumnName("sequence_number"); 95 | 96 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("SequenceNumber")); 97 | 98 | b.Property("Body") 99 | .IsRequired() 100 | .HasColumnType("nvarchar(max)") 101 | .HasColumnName("body"); 102 | 103 | b.Property("ContentType") 104 | .IsRequired() 105 | .HasMaxLength(256) 106 | .HasColumnType("nvarchar(256)") 107 | .HasColumnName("content_type"); 108 | 109 | b.Property("ConversationId") 110 | .HasColumnType("uniqueidentifier") 111 | .HasColumnName("conversation_id"); 112 | 113 | b.Property("CorrelationId") 114 | .HasColumnType("uniqueidentifier") 115 | .HasColumnName("correlation_id"); 116 | 117 | b.Property("DestinationAddress") 118 | .HasMaxLength(256) 119 | .HasColumnType("nvarchar(256)") 120 | .HasColumnName("destination_address"); 121 | 122 | b.Property("EnqueueTime") 123 | .HasColumnType("datetime2") 124 | .HasColumnName("enqueue_time"); 125 | 126 | b.Property("ExpirationTime") 127 | .HasColumnType("datetime2") 128 | .HasColumnName("expiration_time"); 129 | 130 | b.Property("FaultAddress") 131 | .HasMaxLength(256) 132 | .HasColumnType("nvarchar(256)") 133 | .HasColumnName("fault_address"); 134 | 135 | b.Property("Headers") 136 | .HasColumnType("nvarchar(max)") 137 | .HasColumnName("headers"); 138 | 139 | b.Property("InboxConsumerId") 140 | .HasColumnType("uniqueidentifier") 141 | .HasColumnName("inbox_consumer_id"); 142 | 143 | b.Property("InboxMessageId") 144 | .HasColumnType("uniqueidentifier") 145 | .HasColumnName("inbox_message_id"); 146 | 147 | b.Property("InitiatorId") 148 | .HasColumnType("uniqueidentifier") 149 | .HasColumnName("initiator_id"); 150 | 151 | b.Property("MessageId") 152 | .HasColumnType("uniqueidentifier") 153 | .HasColumnName("message_id"); 154 | 155 | b.Property("MessageType") 156 | .IsRequired() 157 | .HasColumnType("nvarchar(max)") 158 | .HasColumnName("message_type"); 159 | 160 | b.Property("OutboxId") 161 | .HasColumnType("uniqueidentifier") 162 | .HasColumnName("outbox_id"); 163 | 164 | b.Property("Properties") 165 | .HasColumnType("nvarchar(max)") 166 | .HasColumnName("properties"); 167 | 168 | b.Property("RequestId") 169 | .HasColumnType("uniqueidentifier") 170 | .HasColumnName("request_id"); 171 | 172 | b.Property("ResponseAddress") 173 | .HasMaxLength(256) 174 | .HasColumnType("nvarchar(256)") 175 | .HasColumnName("response_address"); 176 | 177 | b.Property("SentTime") 178 | .HasColumnType("datetime2") 179 | .HasColumnName("sent_time"); 180 | 181 | b.Property("SourceAddress") 182 | .HasMaxLength(256) 183 | .HasColumnType("nvarchar(256)") 184 | .HasColumnName("source_address"); 185 | 186 | b.HasKey("SequenceNumber"); 187 | 188 | b.HasIndex("EnqueueTime"); 189 | 190 | b.HasIndex("ExpirationTime"); 191 | 192 | b.HasIndex("OutboxId", "SequenceNumber") 193 | .IsUnique() 194 | .HasFilter("[outbox_id] IS NOT NULL"); 195 | 196 | b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") 197 | .IsUnique() 198 | .HasFilter("[inbox_message_id] IS NOT NULL AND [inbox_consumer_id] IS NOT NULL"); 199 | 200 | b.ToTable("outbox_message", "sample"); 201 | }); 202 | 203 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => 204 | { 205 | b.Property("OutboxId") 206 | .ValueGeneratedOnAdd() 207 | .HasColumnType("uniqueidentifier") 208 | .HasColumnName("outbox_id"); 209 | 210 | b.Property("Created") 211 | .HasColumnType("datetime2") 212 | .HasColumnName("created"); 213 | 214 | b.Property("Delivered") 215 | .HasColumnType("datetime2") 216 | .HasColumnName("delivered"); 217 | 218 | b.Property("LastSequenceNumber") 219 | .HasColumnType("bigint") 220 | .HasColumnName("last_sequence_number"); 221 | 222 | b.Property("LockId") 223 | .HasColumnType("uniqueidentifier") 224 | .HasColumnName("lock_id"); 225 | 226 | b.Property("RowVersion") 227 | .IsConcurrencyToken() 228 | .ValueGeneratedOnAddOrUpdate() 229 | .HasColumnType("rowversion") 230 | .HasColumnName("row_version"); 231 | 232 | b.HasKey("OutboxId"); 233 | 234 | b.HasIndex("Created"); 235 | 236 | b.ToTable("outbox_state", "sample"); 237 | }); 238 | 239 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 240 | { 241 | b.Property("CorrelationId") 242 | .HasColumnType("uniqueidentifier") 243 | .HasColumnName("correlation_id"); 244 | 245 | b.Property("CurrentState") 246 | .HasColumnType("int") 247 | .HasColumnName("current_state"); 248 | 249 | b.Property("Faulted") 250 | .HasColumnType("datetime2") 251 | .HasColumnName("faulted"); 252 | 253 | b.Property("InstanceAddress") 254 | .HasColumnType("nvarchar(max)") 255 | .HasColumnName("instance_address"); 256 | 257 | b.Property("JobId") 258 | .HasColumnType("uniqueidentifier") 259 | .HasColumnName("job_id"); 260 | 261 | b.Property("RetryAttempt") 262 | .HasColumnType("int") 263 | .HasColumnName("retry_attempt"); 264 | 265 | b.Property("ServiceAddress") 266 | .HasColumnType("nvarchar(max)") 267 | .HasColumnName("service_address"); 268 | 269 | b.Property("Started") 270 | .HasColumnType("datetime2") 271 | .HasColumnName("started"); 272 | 273 | b.Property("StatusCheckTokenId") 274 | .HasColumnType("uniqueidentifier") 275 | .HasColumnName("status_check_token_id"); 276 | 277 | b.HasKey("CorrelationId"); 278 | 279 | b.HasIndex("JobId", "RetryAttempt") 280 | .IsUnique(); 281 | 282 | b.ToTable("job_attempt_saga", "sample"); 283 | }); 284 | 285 | modelBuilder.Entity("MassTransit.JobSaga", b => 286 | { 287 | b.Property("CorrelationId") 288 | .HasColumnType("uniqueidentifier") 289 | .HasColumnName("correlation_id"); 290 | 291 | b.Property("AttemptId") 292 | .HasColumnType("uniqueidentifier") 293 | .HasColumnName("attempt_id"); 294 | 295 | b.Property("Completed") 296 | .HasColumnType("datetime2") 297 | .HasColumnName("completed"); 298 | 299 | b.Property("CurrentState") 300 | .HasColumnType("int") 301 | .HasColumnName("current_state"); 302 | 303 | b.Property("Duration") 304 | .HasColumnType("time") 305 | .HasColumnName("duration"); 306 | 307 | b.Property("Faulted") 308 | .HasColumnType("datetime2") 309 | .HasColumnName("faulted"); 310 | 311 | b.Property("Job") 312 | .HasColumnType("nvarchar(max)") 313 | .HasColumnName("job"); 314 | 315 | b.Property("JobRetryDelayToken") 316 | .HasColumnType("uniqueidentifier") 317 | .HasColumnName("job_retry_delay_token"); 318 | 319 | b.Property("JobSlotWaitToken") 320 | .HasColumnType("uniqueidentifier") 321 | .HasColumnName("job_slot_wait_token"); 322 | 323 | b.Property("JobTimeout") 324 | .HasColumnType("time") 325 | .HasColumnName("job_timeout"); 326 | 327 | b.Property("JobTypeId") 328 | .HasColumnType("uniqueidentifier") 329 | .HasColumnName("job_type_id"); 330 | 331 | b.Property("Reason") 332 | .HasColumnType("nvarchar(max)") 333 | .HasColumnName("reason"); 334 | 335 | b.Property("RetryAttempt") 336 | .HasColumnType("int") 337 | .HasColumnName("retry_attempt"); 338 | 339 | b.Property("ServiceAddress") 340 | .HasColumnType("nvarchar(max)") 341 | .HasColumnName("service_address"); 342 | 343 | b.Property("Started") 344 | .HasColumnType("datetime2") 345 | .HasColumnName("started"); 346 | 347 | b.Property("Submitted") 348 | .HasColumnType("datetime2") 349 | .HasColumnName("submitted"); 350 | 351 | b.HasKey("CorrelationId"); 352 | 353 | b.ToTable("job_saga", "sample"); 354 | }); 355 | 356 | modelBuilder.Entity("MassTransit.JobTypeSaga", b => 357 | { 358 | b.Property("CorrelationId") 359 | .HasColumnType("uniqueidentifier") 360 | .HasColumnName("correlation_id"); 361 | 362 | b.Property("ActiveJobCount") 363 | .HasColumnType("int") 364 | .HasColumnName("active_job_count"); 365 | 366 | b.Property("ActiveJobs") 367 | .HasColumnType("nvarchar(max)") 368 | .HasColumnName("active_jobs"); 369 | 370 | b.Property("ConcurrentJobLimit") 371 | .HasColumnType("int") 372 | .HasColumnName("concurrent_job_limit"); 373 | 374 | b.Property("CurrentState") 375 | .HasColumnType("int") 376 | .HasColumnName("current_state"); 377 | 378 | b.Property("Instances") 379 | .HasColumnType("nvarchar(max)") 380 | .HasColumnName("instances"); 381 | 382 | b.Property("Name") 383 | .HasColumnType("nvarchar(max)") 384 | .HasColumnName("name"); 385 | 386 | b.Property("OverrideJobLimit") 387 | .HasColumnType("int") 388 | .HasColumnName("override_job_limit"); 389 | 390 | b.Property("OverrideLimitExpiration") 391 | .HasColumnType("datetime2") 392 | .HasColumnName("override_limit_expiration"); 393 | 394 | b.HasKey("CorrelationId"); 395 | 396 | b.ToTable("job_type_saga", "sample"); 397 | }); 398 | 399 | modelBuilder.Entity("Sample.Components.StateMachines.RegistrationState", b => 400 | { 401 | b.Property("CorrelationId") 402 | .HasColumnType("uniqueidentifier") 403 | .HasColumnName("correlation_id"); 404 | 405 | b.Property("CardNumber") 406 | .HasColumnType("nvarchar(max)") 407 | .HasColumnName("card_number"); 408 | 409 | b.Property("CurrentState") 410 | .HasColumnType("nvarchar(max)") 411 | .HasColumnName("current_state"); 412 | 413 | b.Property("EventId") 414 | .HasColumnType("nvarchar(max)") 415 | .HasColumnName("event_id"); 416 | 417 | b.Property("ParticipantCategory") 418 | .HasColumnType("nvarchar(max)") 419 | .HasColumnName("participant_category"); 420 | 421 | b.Property("ParticipantEmailAddress") 422 | .HasColumnType("nvarchar(max)") 423 | .HasColumnName("participant_email_address"); 424 | 425 | b.Property("ParticipantLicenseExpirationDate") 426 | .HasColumnType("datetime2") 427 | .HasColumnName("participant_license_expiration_date"); 428 | 429 | b.Property("ParticipantLicenseNumber") 430 | .HasColumnType("nvarchar(max)") 431 | .HasColumnName("participant_license_number"); 432 | 433 | b.Property("RaceId") 434 | .HasColumnType("nvarchar(max)") 435 | .HasColumnName("race_id"); 436 | 437 | b.Property("Reason") 438 | .HasColumnType("nvarchar(max)") 439 | .HasColumnName("reason"); 440 | 441 | b.Property("RegistrationId") 442 | .HasColumnType("uniqueidentifier") 443 | .HasColumnName("registration_id"); 444 | 445 | b.Property("RetryAttempt") 446 | .HasColumnType("int") 447 | .HasColumnName("retry_attempt"); 448 | 449 | b.Property("ScheduleRetryToken") 450 | .HasColumnType("uniqueidentifier") 451 | .HasColumnName("schedule_retry_token"); 452 | 453 | b.HasKey("CorrelationId"); 454 | 455 | b.ToTable("registration_state", "sample"); 456 | }); 457 | #pragma warning restore 612, 618 458 | } 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /src/Sample.Api/Migrations/SampleDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 6 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 7 | using Sample.Components; 8 | 9 | #nullable disable 10 | 11 | namespace Sample.Api.Migrations 12 | { 13 | [DbContext(typeof(SampleDbContext))] 14 | partial class SampleDbContextModelSnapshot : ModelSnapshot 15 | { 16 | protected override void BuildModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasDefaultSchema("sample") 21 | .HasAnnotation("ProductVersion", "8.0.0") 22 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 23 | 24 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 25 | 26 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => 27 | { 28 | b.Property("Id") 29 | .ValueGeneratedOnAdd() 30 | .HasColumnType("bigint") 31 | .HasColumnName("id"); 32 | 33 | NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); 34 | 35 | b.Property("Consumed") 36 | .HasColumnType("timestamp with time zone") 37 | .HasColumnName("consumed"); 38 | 39 | b.Property("ConsumerId") 40 | .HasColumnType("uuid") 41 | .HasColumnName("consumer_id"); 42 | 43 | b.Property("Delivered") 44 | .HasColumnType("timestamp with time zone") 45 | .HasColumnName("delivered"); 46 | 47 | b.Property("ExpirationTime") 48 | .HasColumnType("timestamp with time zone") 49 | .HasColumnName("expiration_time"); 50 | 51 | b.Property("LastSequenceNumber") 52 | .HasColumnType("bigint") 53 | .HasColumnName("last_sequence_number"); 54 | 55 | b.Property("LockId") 56 | .HasColumnType("uuid") 57 | .HasColumnName("lock_id"); 58 | 59 | b.Property("MessageId") 60 | .HasColumnType("uuid") 61 | .HasColumnName("message_id"); 62 | 63 | b.Property("ReceiveCount") 64 | .HasColumnType("integer") 65 | .HasColumnName("receive_count"); 66 | 67 | b.Property("Received") 68 | .HasColumnType("timestamp with time zone") 69 | .HasColumnName("received"); 70 | 71 | b.Property("RowVersion") 72 | .IsConcurrencyToken() 73 | .ValueGeneratedOnAddOrUpdate() 74 | .HasColumnType("bytea") 75 | .HasColumnName("row_version"); 76 | 77 | b.HasKey("Id"); 78 | 79 | b.HasIndex("Delivered"); 80 | 81 | b.ToTable("inbox_state", "sample"); 82 | }); 83 | 84 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 85 | { 86 | b.Property("SequenceNumber") 87 | .ValueGeneratedOnAdd() 88 | .HasColumnType("bigint") 89 | .HasColumnName("sequence_number"); 90 | 91 | NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); 92 | 93 | b.Property("Body") 94 | .IsRequired() 95 | .HasColumnType("text") 96 | .HasColumnName("body"); 97 | 98 | b.Property("ContentType") 99 | .IsRequired() 100 | .HasMaxLength(256) 101 | .HasColumnType("character varying(256)") 102 | .HasColumnName("content_type"); 103 | 104 | b.Property("ConversationId") 105 | .HasColumnType("uuid") 106 | .HasColumnName("conversation_id"); 107 | 108 | b.Property("CorrelationId") 109 | .HasColumnType("uuid") 110 | .HasColumnName("correlation_id"); 111 | 112 | b.Property("DestinationAddress") 113 | .HasMaxLength(256) 114 | .HasColumnType("character varying(256)") 115 | .HasColumnName("destination_address"); 116 | 117 | b.Property("EnqueueTime") 118 | .HasColumnType("timestamp with time zone") 119 | .HasColumnName("enqueue_time"); 120 | 121 | b.Property("ExpirationTime") 122 | .HasColumnType("timestamp with time zone") 123 | .HasColumnName("expiration_time"); 124 | 125 | b.Property("FaultAddress") 126 | .HasMaxLength(256) 127 | .HasColumnType("character varying(256)") 128 | .HasColumnName("fault_address"); 129 | 130 | b.Property("Headers") 131 | .HasColumnType("text") 132 | .HasColumnName("headers"); 133 | 134 | b.Property("InboxConsumerId") 135 | .HasColumnType("uuid") 136 | .HasColumnName("inbox_consumer_id"); 137 | 138 | b.Property("InboxMessageId") 139 | .HasColumnType("uuid") 140 | .HasColumnName("inbox_message_id"); 141 | 142 | b.Property("InitiatorId") 143 | .HasColumnType("uuid") 144 | .HasColumnName("initiator_id"); 145 | 146 | b.Property("MessageId") 147 | .HasColumnType("uuid") 148 | .HasColumnName("message_id"); 149 | 150 | b.Property("MessageType") 151 | .IsRequired() 152 | .HasColumnType("text") 153 | .HasColumnName("message_type"); 154 | 155 | b.Property("OutboxId") 156 | .HasColumnType("uuid") 157 | .HasColumnName("outbox_id"); 158 | 159 | b.Property("Properties") 160 | .HasColumnType("text") 161 | .HasColumnName("properties"); 162 | 163 | b.Property("RequestId") 164 | .HasColumnType("uuid") 165 | .HasColumnName("request_id"); 166 | 167 | b.Property("ResponseAddress") 168 | .HasMaxLength(256) 169 | .HasColumnType("character varying(256)") 170 | .HasColumnName("response_address"); 171 | 172 | b.Property("SentTime") 173 | .HasColumnType("timestamp with time zone") 174 | .HasColumnName("sent_time"); 175 | 176 | b.Property("SourceAddress") 177 | .HasMaxLength(256) 178 | .HasColumnType("character varying(256)") 179 | .HasColumnName("source_address"); 180 | 181 | b.HasKey("SequenceNumber"); 182 | 183 | b.HasIndex("EnqueueTime"); 184 | 185 | b.HasIndex("ExpirationTime"); 186 | 187 | b.HasIndex("OutboxId", "SequenceNumber") 188 | .IsUnique(); 189 | 190 | b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") 191 | .IsUnique(); 192 | 193 | b.ToTable("outbox_message", "sample"); 194 | }); 195 | 196 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => 197 | { 198 | b.Property("OutboxId") 199 | .ValueGeneratedOnAdd() 200 | .HasColumnType("uuid") 201 | .HasColumnName("outbox_id"); 202 | 203 | b.Property("Created") 204 | .HasColumnType("timestamp with time zone") 205 | .HasColumnName("created"); 206 | 207 | b.Property("Delivered") 208 | .HasColumnType("timestamp with time zone") 209 | .HasColumnName("delivered"); 210 | 211 | b.Property("LastSequenceNumber") 212 | .HasColumnType("bigint") 213 | .HasColumnName("last_sequence_number"); 214 | 215 | b.Property("LockId") 216 | .HasColumnType("uuid") 217 | .HasColumnName("lock_id"); 218 | 219 | b.Property("RowVersion") 220 | .IsConcurrencyToken() 221 | .ValueGeneratedOnAddOrUpdate() 222 | .HasColumnType("bytea") 223 | .HasColumnName("row_version"); 224 | 225 | b.HasKey("OutboxId"); 226 | 227 | b.HasIndex("Created"); 228 | 229 | b.ToTable("outbox_state", "sample"); 230 | }); 231 | 232 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 233 | { 234 | b.Property("CorrelationId") 235 | .HasColumnType("uuid") 236 | .HasColumnName("correlation_id"); 237 | 238 | b.Property("CurrentState") 239 | .HasColumnType("integer") 240 | .HasColumnName("current_state"); 241 | 242 | b.Property("Faulted") 243 | .HasColumnType("timestamp with time zone") 244 | .HasColumnName("faulted"); 245 | 246 | b.Property("InstanceAddress") 247 | .HasColumnType("text") 248 | .HasColumnName("instance_address"); 249 | 250 | b.Property("JobId") 251 | .HasColumnType("uuid") 252 | .HasColumnName("job_id"); 253 | 254 | b.Property("RetryAttempt") 255 | .HasColumnType("integer") 256 | .HasColumnName("retry_attempt"); 257 | 258 | b.Property("ServiceAddress") 259 | .HasColumnType("text") 260 | .HasColumnName("service_address"); 261 | 262 | b.Property("Started") 263 | .HasColumnType("timestamp with time zone") 264 | .HasColumnName("started"); 265 | 266 | b.Property("StatusCheckTokenId") 267 | .HasColumnType("uuid") 268 | .HasColumnName("status_check_token_id"); 269 | 270 | b.HasKey("CorrelationId"); 271 | 272 | b.HasIndex("JobId", "RetryAttempt") 273 | .IsUnique(); 274 | 275 | b.ToTable("job_attempt_saga", "sample"); 276 | }); 277 | 278 | modelBuilder.Entity("MassTransit.JobSaga", b => 279 | { 280 | b.Property("CorrelationId") 281 | .HasColumnType("uuid") 282 | .HasColumnName("correlation_id"); 283 | 284 | b.Property("AttemptId") 285 | .HasColumnType("uuid") 286 | .HasColumnName("attempt_id"); 287 | 288 | b.Property("Completed") 289 | .HasColumnType("timestamp with time zone") 290 | .HasColumnName("completed"); 291 | 292 | b.Property("CronExpression") 293 | .HasColumnType("text") 294 | .HasColumnName("cron_expression"); 295 | 296 | b.Property("CurrentState") 297 | .HasColumnType("integer") 298 | .HasColumnName("current_state"); 299 | 300 | b.Property("Duration") 301 | .HasColumnType("interval") 302 | .HasColumnName("duration"); 303 | 304 | b.Property("EndDate") 305 | .HasColumnType("timestamp with time zone") 306 | .HasColumnName("end_date"); 307 | 308 | b.Property("Faulted") 309 | .HasColumnType("timestamp with time zone") 310 | .HasColumnName("faulted"); 311 | 312 | b.Property("IncompleteAttempts") 313 | .HasColumnType("text") 314 | .HasColumnName("incomplete_attempts"); 315 | 316 | b.Property("Job") 317 | .HasColumnType("text") 318 | .HasColumnName("job"); 319 | 320 | b.Property("JobRetryDelayToken") 321 | .HasColumnType("uuid") 322 | .HasColumnName("job_retry_delay_token"); 323 | 324 | b.Property("JobSlotWaitToken") 325 | .HasColumnType("uuid") 326 | .HasColumnName("job_slot_wait_token"); 327 | 328 | b.Property("JobState") 329 | .HasColumnType("text") 330 | .HasColumnName("job_state"); 331 | 332 | b.Property("JobTimeout") 333 | .HasColumnType("interval") 334 | .HasColumnName("job_timeout"); 335 | 336 | b.Property("JobTypeId") 337 | .HasColumnType("uuid") 338 | .HasColumnName("job_type_id"); 339 | 340 | b.Property("LastProgressLimit") 341 | .HasColumnType("bigint") 342 | .HasColumnName("last_progress_limit"); 343 | 344 | b.Property("LastProgressSequenceNumber") 345 | .HasColumnType("bigint") 346 | .HasColumnName("last_progress_sequence_number"); 347 | 348 | b.Property("LastProgressValue") 349 | .HasColumnType("bigint") 350 | .HasColumnName("last_progress_value"); 351 | 352 | b.Property("NextStartDate") 353 | .HasColumnType("timestamp with time zone") 354 | .HasColumnName("next_start_date"); 355 | 356 | b.Property("Reason") 357 | .HasColumnType("text") 358 | .HasColumnName("reason"); 359 | 360 | b.Property("RetryAttempt") 361 | .HasColumnType("integer") 362 | .HasColumnName("retry_attempt"); 363 | 364 | b.Property("ServiceAddress") 365 | .HasColumnType("text") 366 | .HasColumnName("service_address"); 367 | 368 | b.Property("StartDate") 369 | .HasColumnType("timestamp with time zone") 370 | .HasColumnName("start_date"); 371 | 372 | b.Property("Started") 373 | .HasColumnType("timestamp with time zone") 374 | .HasColumnName("started"); 375 | 376 | b.Property("Submitted") 377 | .HasColumnType("timestamp with time zone") 378 | .HasColumnName("submitted"); 379 | 380 | b.Property("TimeZoneId") 381 | .HasColumnType("text") 382 | .HasColumnName("time_zone_id"); 383 | 384 | b.HasKey("CorrelationId"); 385 | 386 | b.ToTable("job_saga", "sample"); 387 | }); 388 | 389 | modelBuilder.Entity("MassTransit.JobTypeSaga", b => 390 | { 391 | b.Property("CorrelationId") 392 | .HasColumnType("uuid") 393 | .HasColumnName("correlation_id"); 394 | 395 | b.Property("ActiveJobCount") 396 | .HasColumnType("integer") 397 | .HasColumnName("active_job_count"); 398 | 399 | b.Property("ActiveJobs") 400 | .HasColumnType("text") 401 | .HasColumnName("active_jobs"); 402 | 403 | b.Property("ConcurrentJobLimit") 404 | .HasColumnType("integer") 405 | .HasColumnName("concurrent_job_limit"); 406 | 407 | b.Property("CurrentState") 408 | .HasColumnType("integer") 409 | .HasColumnName("current_state"); 410 | 411 | b.Property("GlobalConcurrentJobLimit") 412 | .HasColumnType("integer") 413 | .HasColumnName("global_concurrent_job_limit"); 414 | 415 | b.Property("Instances") 416 | .HasColumnType("text") 417 | .HasColumnName("instances"); 418 | 419 | b.Property("Name") 420 | .HasColumnType("text") 421 | .HasColumnName("name"); 422 | 423 | b.Property("OverrideJobLimit") 424 | .HasColumnType("integer") 425 | .HasColumnName("override_job_limit"); 426 | 427 | b.Property("OverrideLimitExpiration") 428 | .HasColumnType("timestamp with time zone") 429 | .HasColumnName("override_limit_expiration"); 430 | 431 | b.Property("Properties") 432 | .HasColumnType("text") 433 | .HasColumnName("properties"); 434 | 435 | b.HasKey("CorrelationId"); 436 | 437 | b.ToTable("job_type_saga", "sample"); 438 | }); 439 | 440 | modelBuilder.Entity("Sample.Components.StateMachines.RegistrationState", b => 441 | { 442 | b.Property("CorrelationId") 443 | .HasColumnType("uuid") 444 | .HasColumnName("correlation_id"); 445 | 446 | b.Property("CardNumber") 447 | .HasColumnType("text") 448 | .HasColumnName("card_number"); 449 | 450 | b.Property("CurrentState") 451 | .HasColumnType("text") 452 | .HasColumnName("current_state"); 453 | 454 | b.Property("EventId") 455 | .HasColumnType("text") 456 | .HasColumnName("event_id"); 457 | 458 | b.Property("ParticipantCategory") 459 | .HasColumnType("text") 460 | .HasColumnName("participant_category"); 461 | 462 | b.Property("ParticipantEmailAddress") 463 | .HasColumnType("text") 464 | .HasColumnName("participant_email_address"); 465 | 466 | b.Property("ParticipantLicenseExpirationDate") 467 | .HasColumnType("timestamp with time zone") 468 | .HasColumnName("participant_license_expiration_date"); 469 | 470 | b.Property("ParticipantLicenseNumber") 471 | .HasColumnType("text") 472 | .HasColumnName("participant_license_number"); 473 | 474 | b.Property("RaceId") 475 | .HasColumnType("text") 476 | .HasColumnName("race_id"); 477 | 478 | b.Property("Reason") 479 | .HasColumnType("text") 480 | .HasColumnName("reason"); 481 | 482 | b.Property("RegistrationId") 483 | .HasColumnType("uuid") 484 | .HasColumnName("registration_id"); 485 | 486 | b.Property("RetryAttempt") 487 | .HasColumnType("integer") 488 | .HasColumnName("retry_attempt"); 489 | 490 | b.Property("ScheduleRetryToken") 491 | .HasColumnType("uuid") 492 | .HasColumnName("schedule_retry_token"); 493 | 494 | b.HasKey("CorrelationId"); 495 | 496 | b.ToTable("registration_state", "sample"); 497 | }); 498 | 499 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 500 | { 501 | b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null) 502 | .WithMany() 503 | .HasForeignKey("OutboxId"); 504 | 505 | b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null) 506 | .WithMany() 507 | .HasForeignKey("InboxMessageId", "InboxConsumerId") 508 | .HasPrincipalKey("MessageId", "ConsumerId"); 509 | }); 510 | 511 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 512 | { 513 | b.HasOne("MassTransit.JobSaga", null) 514 | .WithMany() 515 | .HasForeignKey("JobId") 516 | .OnDelete(DeleteBehavior.Cascade) 517 | .IsRequired(); 518 | }); 519 | #pragma warning restore 612, 618 520 | } 521 | } 522 | } 523 | -------------------------------------------------------------------------------- /src/Sample.Api/Migrations/20241004184848_Updated.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Migrations; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; 8 | using Sample.Components; 9 | 10 | #nullable disable 11 | 12 | namespace Sample.Api.Migrations 13 | { 14 | [DbContext(typeof(SampleDbContext))] 15 | [Migration("20241004184848_Updated")] 16 | partial class Updated 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasDefaultSchema("sample") 24 | .HasAnnotation("ProductVersion", "8.0.0") 25 | .HasAnnotation("Relational:MaxIdentifierLength", 63); 26 | 27 | NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); 28 | 29 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => 30 | { 31 | b.Property("Id") 32 | .ValueGeneratedOnAdd() 33 | .HasColumnType("bigint") 34 | .HasColumnName("id"); 35 | 36 | NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); 37 | 38 | b.Property("Consumed") 39 | .HasColumnType("timestamp with time zone") 40 | .HasColumnName("consumed"); 41 | 42 | b.Property("ConsumerId") 43 | .HasColumnType("uuid") 44 | .HasColumnName("consumer_id"); 45 | 46 | b.Property("Delivered") 47 | .HasColumnType("timestamp with time zone") 48 | .HasColumnName("delivered"); 49 | 50 | b.Property("ExpirationTime") 51 | .HasColumnType("timestamp with time zone") 52 | .HasColumnName("expiration_time"); 53 | 54 | b.Property("LastSequenceNumber") 55 | .HasColumnType("bigint") 56 | .HasColumnName("last_sequence_number"); 57 | 58 | b.Property("LockId") 59 | .HasColumnType("uuid") 60 | .HasColumnName("lock_id"); 61 | 62 | b.Property("MessageId") 63 | .HasColumnType("uuid") 64 | .HasColumnName("message_id"); 65 | 66 | b.Property("ReceiveCount") 67 | .HasColumnType("integer") 68 | .HasColumnName("receive_count"); 69 | 70 | b.Property("Received") 71 | .HasColumnType("timestamp with time zone") 72 | .HasColumnName("received"); 73 | 74 | b.Property("RowVersion") 75 | .IsConcurrencyToken() 76 | .ValueGeneratedOnAddOrUpdate() 77 | .HasColumnType("bytea") 78 | .HasColumnName("row_version"); 79 | 80 | b.HasKey("Id"); 81 | 82 | b.HasIndex("Delivered"); 83 | 84 | b.ToTable("inbox_state", "sample"); 85 | }); 86 | 87 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 88 | { 89 | b.Property("SequenceNumber") 90 | .ValueGeneratedOnAdd() 91 | .HasColumnType("bigint") 92 | .HasColumnName("sequence_number"); 93 | 94 | NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); 95 | 96 | b.Property("Body") 97 | .IsRequired() 98 | .HasColumnType("text") 99 | .HasColumnName("body"); 100 | 101 | b.Property("ContentType") 102 | .IsRequired() 103 | .HasMaxLength(256) 104 | .HasColumnType("character varying(256)") 105 | .HasColumnName("content_type"); 106 | 107 | b.Property("ConversationId") 108 | .HasColumnType("uuid") 109 | .HasColumnName("conversation_id"); 110 | 111 | b.Property("CorrelationId") 112 | .HasColumnType("uuid") 113 | .HasColumnName("correlation_id"); 114 | 115 | b.Property("DestinationAddress") 116 | .HasMaxLength(256) 117 | .HasColumnType("character varying(256)") 118 | .HasColumnName("destination_address"); 119 | 120 | b.Property("EnqueueTime") 121 | .HasColumnType("timestamp with time zone") 122 | .HasColumnName("enqueue_time"); 123 | 124 | b.Property("ExpirationTime") 125 | .HasColumnType("timestamp with time zone") 126 | .HasColumnName("expiration_time"); 127 | 128 | b.Property("FaultAddress") 129 | .HasMaxLength(256) 130 | .HasColumnType("character varying(256)") 131 | .HasColumnName("fault_address"); 132 | 133 | b.Property("Headers") 134 | .HasColumnType("text") 135 | .HasColumnName("headers"); 136 | 137 | b.Property("InboxConsumerId") 138 | .HasColumnType("uuid") 139 | .HasColumnName("inbox_consumer_id"); 140 | 141 | b.Property("InboxMessageId") 142 | .HasColumnType("uuid") 143 | .HasColumnName("inbox_message_id"); 144 | 145 | b.Property("InitiatorId") 146 | .HasColumnType("uuid") 147 | .HasColumnName("initiator_id"); 148 | 149 | b.Property("MessageId") 150 | .HasColumnType("uuid") 151 | .HasColumnName("message_id"); 152 | 153 | b.Property("MessageType") 154 | .IsRequired() 155 | .HasColumnType("text") 156 | .HasColumnName("message_type"); 157 | 158 | b.Property("OutboxId") 159 | .HasColumnType("uuid") 160 | .HasColumnName("outbox_id"); 161 | 162 | b.Property("Properties") 163 | .HasColumnType("text") 164 | .HasColumnName("properties"); 165 | 166 | b.Property("RequestId") 167 | .HasColumnType("uuid") 168 | .HasColumnName("request_id"); 169 | 170 | b.Property("ResponseAddress") 171 | .HasMaxLength(256) 172 | .HasColumnType("character varying(256)") 173 | .HasColumnName("response_address"); 174 | 175 | b.Property("SentTime") 176 | .HasColumnType("timestamp with time zone") 177 | .HasColumnName("sent_time"); 178 | 179 | b.Property("SourceAddress") 180 | .HasMaxLength(256) 181 | .HasColumnType("character varying(256)") 182 | .HasColumnName("source_address"); 183 | 184 | b.HasKey("SequenceNumber"); 185 | 186 | b.HasIndex("EnqueueTime"); 187 | 188 | b.HasIndex("ExpirationTime"); 189 | 190 | b.HasIndex("OutboxId", "SequenceNumber") 191 | .IsUnique(); 192 | 193 | b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") 194 | .IsUnique(); 195 | 196 | b.ToTable("outbox_message", "sample"); 197 | }); 198 | 199 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => 200 | { 201 | b.Property("OutboxId") 202 | .ValueGeneratedOnAdd() 203 | .HasColumnType("uuid") 204 | .HasColumnName("outbox_id"); 205 | 206 | b.Property("Created") 207 | .HasColumnType("timestamp with time zone") 208 | .HasColumnName("created"); 209 | 210 | b.Property("Delivered") 211 | .HasColumnType("timestamp with time zone") 212 | .HasColumnName("delivered"); 213 | 214 | b.Property("LastSequenceNumber") 215 | .HasColumnType("bigint") 216 | .HasColumnName("last_sequence_number"); 217 | 218 | b.Property("LockId") 219 | .HasColumnType("uuid") 220 | .HasColumnName("lock_id"); 221 | 222 | b.Property("RowVersion") 223 | .IsConcurrencyToken() 224 | .ValueGeneratedOnAddOrUpdate() 225 | .HasColumnType("bytea") 226 | .HasColumnName("row_version"); 227 | 228 | b.HasKey("OutboxId"); 229 | 230 | b.HasIndex("Created"); 231 | 232 | b.ToTable("outbox_state", "sample"); 233 | }); 234 | 235 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 236 | { 237 | b.Property("CorrelationId") 238 | .HasColumnType("uuid") 239 | .HasColumnName("correlation_id"); 240 | 241 | b.Property("CurrentState") 242 | .HasColumnType("integer") 243 | .HasColumnName("current_state"); 244 | 245 | b.Property("Faulted") 246 | .HasColumnType("timestamp with time zone") 247 | .HasColumnName("faulted"); 248 | 249 | b.Property("InstanceAddress") 250 | .HasColumnType("text") 251 | .HasColumnName("instance_address"); 252 | 253 | b.Property("JobId") 254 | .HasColumnType("uuid") 255 | .HasColumnName("job_id"); 256 | 257 | b.Property("RetryAttempt") 258 | .HasColumnType("integer") 259 | .HasColumnName("retry_attempt"); 260 | 261 | b.Property("ServiceAddress") 262 | .HasColumnType("text") 263 | .HasColumnName("service_address"); 264 | 265 | b.Property("Started") 266 | .HasColumnType("timestamp with time zone") 267 | .HasColumnName("started"); 268 | 269 | b.Property("StatusCheckTokenId") 270 | .HasColumnType("uuid") 271 | .HasColumnName("status_check_token_id"); 272 | 273 | b.HasKey("CorrelationId"); 274 | 275 | b.HasIndex("JobId", "RetryAttempt") 276 | .IsUnique(); 277 | 278 | b.ToTable("job_attempt_saga", "sample"); 279 | }); 280 | 281 | modelBuilder.Entity("MassTransit.JobSaga", b => 282 | { 283 | b.Property("CorrelationId") 284 | .HasColumnType("uuid") 285 | .HasColumnName("correlation_id"); 286 | 287 | b.Property("AttemptId") 288 | .HasColumnType("uuid") 289 | .HasColumnName("attempt_id"); 290 | 291 | b.Property("Completed") 292 | .HasColumnType("timestamp with time zone") 293 | .HasColumnName("completed"); 294 | 295 | b.Property("CronExpression") 296 | .HasColumnType("text") 297 | .HasColumnName("cron_expression"); 298 | 299 | b.Property("CurrentState") 300 | .HasColumnType("integer") 301 | .HasColumnName("current_state"); 302 | 303 | b.Property("Duration") 304 | .HasColumnType("interval") 305 | .HasColumnName("duration"); 306 | 307 | b.Property("EndDate") 308 | .HasColumnType("timestamp with time zone") 309 | .HasColumnName("end_date"); 310 | 311 | b.Property("Faulted") 312 | .HasColumnType("timestamp with time zone") 313 | .HasColumnName("faulted"); 314 | 315 | b.Property("IncompleteAttempts") 316 | .HasColumnType("text") 317 | .HasColumnName("incomplete_attempts"); 318 | 319 | b.Property("Job") 320 | .HasColumnType("text") 321 | .HasColumnName("job"); 322 | 323 | b.Property("JobRetryDelayToken") 324 | .HasColumnType("uuid") 325 | .HasColumnName("job_retry_delay_token"); 326 | 327 | b.Property("JobSlotWaitToken") 328 | .HasColumnType("uuid") 329 | .HasColumnName("job_slot_wait_token"); 330 | 331 | b.Property("JobState") 332 | .HasColumnType("text") 333 | .HasColumnName("job_state"); 334 | 335 | b.Property("JobTimeout") 336 | .HasColumnType("interval") 337 | .HasColumnName("job_timeout"); 338 | 339 | b.Property("JobTypeId") 340 | .HasColumnType("uuid") 341 | .HasColumnName("job_type_id"); 342 | 343 | b.Property("LastProgressLimit") 344 | .HasColumnType("bigint") 345 | .HasColumnName("last_progress_limit"); 346 | 347 | b.Property("LastProgressSequenceNumber") 348 | .HasColumnType("bigint") 349 | .HasColumnName("last_progress_sequence_number"); 350 | 351 | b.Property("LastProgressValue") 352 | .HasColumnType("bigint") 353 | .HasColumnName("last_progress_value"); 354 | 355 | b.Property("NextStartDate") 356 | .HasColumnType("timestamp with time zone") 357 | .HasColumnName("next_start_date"); 358 | 359 | b.Property("Reason") 360 | .HasColumnType("text") 361 | .HasColumnName("reason"); 362 | 363 | b.Property("RetryAttempt") 364 | .HasColumnType("integer") 365 | .HasColumnName("retry_attempt"); 366 | 367 | b.Property("ServiceAddress") 368 | .HasColumnType("text") 369 | .HasColumnName("service_address"); 370 | 371 | b.Property("StartDate") 372 | .HasColumnType("timestamp with time zone") 373 | .HasColumnName("start_date"); 374 | 375 | b.Property("Started") 376 | .HasColumnType("timestamp with time zone") 377 | .HasColumnName("started"); 378 | 379 | b.Property("Submitted") 380 | .HasColumnType("timestamp with time zone") 381 | .HasColumnName("submitted"); 382 | 383 | b.Property("TimeZoneId") 384 | .HasColumnType("text") 385 | .HasColumnName("time_zone_id"); 386 | 387 | b.HasKey("CorrelationId"); 388 | 389 | b.ToTable("job_saga", "sample"); 390 | }); 391 | 392 | modelBuilder.Entity("MassTransit.JobTypeSaga", b => 393 | { 394 | b.Property("CorrelationId") 395 | .HasColumnType("uuid") 396 | .HasColumnName("correlation_id"); 397 | 398 | b.Property("ActiveJobCount") 399 | .HasColumnType("integer") 400 | .HasColumnName("active_job_count"); 401 | 402 | b.Property("ActiveJobs") 403 | .HasColumnType("text") 404 | .HasColumnName("active_jobs"); 405 | 406 | b.Property("ConcurrentJobLimit") 407 | .HasColumnType("integer") 408 | .HasColumnName("concurrent_job_limit"); 409 | 410 | b.Property("CurrentState") 411 | .HasColumnType("integer") 412 | .HasColumnName("current_state"); 413 | 414 | b.Property("GlobalConcurrentJobLimit") 415 | .HasColumnType("integer") 416 | .HasColumnName("global_concurrent_job_limit"); 417 | 418 | b.Property("Instances") 419 | .HasColumnType("text") 420 | .HasColumnName("instances"); 421 | 422 | b.Property("Name") 423 | .HasColumnType("text") 424 | .HasColumnName("name"); 425 | 426 | b.Property("OverrideJobLimit") 427 | .HasColumnType("integer") 428 | .HasColumnName("override_job_limit"); 429 | 430 | b.Property("OverrideLimitExpiration") 431 | .HasColumnType("timestamp with time zone") 432 | .HasColumnName("override_limit_expiration"); 433 | 434 | b.Property("Properties") 435 | .HasColumnType("text") 436 | .HasColumnName("properties"); 437 | 438 | b.HasKey("CorrelationId"); 439 | 440 | b.ToTable("job_type_saga", "sample"); 441 | }); 442 | 443 | modelBuilder.Entity("Sample.Components.StateMachines.RegistrationState", b => 444 | { 445 | b.Property("CorrelationId") 446 | .HasColumnType("uuid") 447 | .HasColumnName("correlation_id"); 448 | 449 | b.Property("CardNumber") 450 | .HasColumnType("text") 451 | .HasColumnName("card_number"); 452 | 453 | b.Property("CurrentState") 454 | .HasColumnType("text") 455 | .HasColumnName("current_state"); 456 | 457 | b.Property("EventId") 458 | .HasColumnType("text") 459 | .HasColumnName("event_id"); 460 | 461 | b.Property("ParticipantCategory") 462 | .HasColumnType("text") 463 | .HasColumnName("participant_category"); 464 | 465 | b.Property("ParticipantEmailAddress") 466 | .HasColumnType("text") 467 | .HasColumnName("participant_email_address"); 468 | 469 | b.Property("ParticipantLicenseExpirationDate") 470 | .HasColumnType("timestamp with time zone") 471 | .HasColumnName("participant_license_expiration_date"); 472 | 473 | b.Property("ParticipantLicenseNumber") 474 | .HasColumnType("text") 475 | .HasColumnName("participant_license_number"); 476 | 477 | b.Property("RaceId") 478 | .HasColumnType("text") 479 | .HasColumnName("race_id"); 480 | 481 | b.Property("Reason") 482 | .HasColumnType("text") 483 | .HasColumnName("reason"); 484 | 485 | b.Property("RegistrationId") 486 | .HasColumnType("uuid") 487 | .HasColumnName("registration_id"); 488 | 489 | b.Property("RetryAttempt") 490 | .HasColumnType("integer") 491 | .HasColumnName("retry_attempt"); 492 | 493 | b.Property("ScheduleRetryToken") 494 | .HasColumnType("uuid") 495 | .HasColumnName("schedule_retry_token"); 496 | 497 | b.HasKey("CorrelationId"); 498 | 499 | b.ToTable("registration_state", "sample"); 500 | }); 501 | 502 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 503 | { 504 | b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null) 505 | .WithMany() 506 | .HasForeignKey("OutboxId"); 507 | 508 | b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null) 509 | .WithMany() 510 | .HasForeignKey("InboxMessageId", "InboxConsumerId") 511 | .HasPrincipalKey("MessageId", "ConsumerId"); 512 | }); 513 | 514 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 515 | { 516 | b.HasOne("MassTransit.JobSaga", null) 517 | .WithMany() 518 | .HasForeignKey("JobId") 519 | .OnDelete(DeleteBehavior.Cascade) 520 | .IsRequired(); 521 | }); 522 | #pragma warning restore 612, 618 523 | } 524 | } 525 | } 526 | -------------------------------------------------------------------------------- /src/Sample.Api.SqlServer/Migrations/20241004184901_Updated.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | using Sample.Components; 9 | 10 | #nullable disable 11 | 12 | namespace Sample.Api.SqlServer.Migrations 13 | { 14 | [DbContext(typeof(SampleDbContext))] 15 | [Migration("20241004184901_Updated")] 16 | partial class Updated 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasDefaultSchema("sample") 24 | .HasAnnotation("ProductVersion", "8.0.0") 25 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 26 | 27 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 28 | 29 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => 30 | { 31 | b.Property("Id") 32 | .ValueGeneratedOnAdd() 33 | .HasColumnType("bigint") 34 | .HasColumnName("id"); 35 | 36 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 37 | 38 | b.Property("Consumed") 39 | .HasColumnType("datetime2") 40 | .HasColumnName("consumed"); 41 | 42 | b.Property("ConsumerId") 43 | .HasColumnType("uniqueidentifier") 44 | .HasColumnName("consumer_id"); 45 | 46 | b.Property("Delivered") 47 | .HasColumnType("datetime2") 48 | .HasColumnName("delivered"); 49 | 50 | b.Property("ExpirationTime") 51 | .HasColumnType("datetime2") 52 | .HasColumnName("expiration_time"); 53 | 54 | b.Property("LastSequenceNumber") 55 | .HasColumnType("bigint") 56 | .HasColumnName("last_sequence_number"); 57 | 58 | b.Property("LockId") 59 | .HasColumnType("uniqueidentifier") 60 | .HasColumnName("lock_id"); 61 | 62 | b.Property("MessageId") 63 | .HasColumnType("uniqueidentifier") 64 | .HasColumnName("message_id"); 65 | 66 | b.Property("ReceiveCount") 67 | .HasColumnType("int") 68 | .HasColumnName("receive_count"); 69 | 70 | b.Property("Received") 71 | .HasColumnType("datetime2") 72 | .HasColumnName("received"); 73 | 74 | b.Property("RowVersion") 75 | .IsConcurrencyToken() 76 | .ValueGeneratedOnAddOrUpdate() 77 | .HasColumnType("rowversion") 78 | .HasColumnName("row_version"); 79 | 80 | b.HasKey("Id"); 81 | 82 | b.HasIndex("Delivered"); 83 | 84 | b.ToTable("inbox_state", "sample"); 85 | }); 86 | 87 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 88 | { 89 | b.Property("SequenceNumber") 90 | .ValueGeneratedOnAdd() 91 | .HasColumnType("bigint") 92 | .HasColumnName("sequence_number"); 93 | 94 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("SequenceNumber")); 95 | 96 | b.Property("Body") 97 | .IsRequired() 98 | .HasColumnType("nvarchar(max)") 99 | .HasColumnName("body"); 100 | 101 | b.Property("ContentType") 102 | .IsRequired() 103 | .HasMaxLength(256) 104 | .HasColumnType("nvarchar(256)") 105 | .HasColumnName("content_type"); 106 | 107 | b.Property("ConversationId") 108 | .HasColumnType("uniqueidentifier") 109 | .HasColumnName("conversation_id"); 110 | 111 | b.Property("CorrelationId") 112 | .HasColumnType("uniqueidentifier") 113 | .HasColumnName("correlation_id"); 114 | 115 | b.Property("DestinationAddress") 116 | .HasMaxLength(256) 117 | .HasColumnType("nvarchar(256)") 118 | .HasColumnName("destination_address"); 119 | 120 | b.Property("EnqueueTime") 121 | .HasColumnType("datetime2") 122 | .HasColumnName("enqueue_time"); 123 | 124 | b.Property("ExpirationTime") 125 | .HasColumnType("datetime2") 126 | .HasColumnName("expiration_time"); 127 | 128 | b.Property("FaultAddress") 129 | .HasMaxLength(256) 130 | .HasColumnType("nvarchar(256)") 131 | .HasColumnName("fault_address"); 132 | 133 | b.Property("Headers") 134 | .HasColumnType("nvarchar(max)") 135 | .HasColumnName("headers"); 136 | 137 | b.Property("InboxConsumerId") 138 | .HasColumnType("uniqueidentifier") 139 | .HasColumnName("inbox_consumer_id"); 140 | 141 | b.Property("InboxMessageId") 142 | .HasColumnType("uniqueidentifier") 143 | .HasColumnName("inbox_message_id"); 144 | 145 | b.Property("InitiatorId") 146 | .HasColumnType("uniqueidentifier") 147 | .HasColumnName("initiator_id"); 148 | 149 | b.Property("MessageId") 150 | .HasColumnType("uniqueidentifier") 151 | .HasColumnName("message_id"); 152 | 153 | b.Property("MessageType") 154 | .IsRequired() 155 | .HasColumnType("nvarchar(max)") 156 | .HasColumnName("message_type"); 157 | 158 | b.Property("OutboxId") 159 | .HasColumnType("uniqueidentifier") 160 | .HasColumnName("outbox_id"); 161 | 162 | b.Property("Properties") 163 | .HasColumnType("nvarchar(max)") 164 | .HasColumnName("properties"); 165 | 166 | b.Property("RequestId") 167 | .HasColumnType("uniqueidentifier") 168 | .HasColumnName("request_id"); 169 | 170 | b.Property("ResponseAddress") 171 | .HasMaxLength(256) 172 | .HasColumnType("nvarchar(256)") 173 | .HasColumnName("response_address"); 174 | 175 | b.Property("SentTime") 176 | .HasColumnType("datetime2") 177 | .HasColumnName("sent_time"); 178 | 179 | b.Property("SourceAddress") 180 | .HasMaxLength(256) 181 | .HasColumnType("nvarchar(256)") 182 | .HasColumnName("source_address"); 183 | 184 | b.HasKey("SequenceNumber"); 185 | 186 | b.HasIndex("EnqueueTime"); 187 | 188 | b.HasIndex("ExpirationTime"); 189 | 190 | b.HasIndex("OutboxId", "SequenceNumber") 191 | .IsUnique() 192 | .HasFilter("[outbox_id] IS NOT NULL"); 193 | 194 | b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") 195 | .IsUnique() 196 | .HasFilter("[inbox_message_id] IS NOT NULL AND [inbox_consumer_id] IS NOT NULL"); 197 | 198 | b.ToTable("outbox_message", "sample"); 199 | }); 200 | 201 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => 202 | { 203 | b.Property("OutboxId") 204 | .ValueGeneratedOnAdd() 205 | .HasColumnType("uniqueidentifier") 206 | .HasColumnName("outbox_id"); 207 | 208 | b.Property("Created") 209 | .HasColumnType("datetime2") 210 | .HasColumnName("created"); 211 | 212 | b.Property("Delivered") 213 | .HasColumnType("datetime2") 214 | .HasColumnName("delivered"); 215 | 216 | b.Property("LastSequenceNumber") 217 | .HasColumnType("bigint") 218 | .HasColumnName("last_sequence_number"); 219 | 220 | b.Property("LockId") 221 | .HasColumnType("uniqueidentifier") 222 | .HasColumnName("lock_id"); 223 | 224 | b.Property("RowVersion") 225 | .IsConcurrencyToken() 226 | .ValueGeneratedOnAddOrUpdate() 227 | .HasColumnType("rowversion") 228 | .HasColumnName("row_version"); 229 | 230 | b.HasKey("OutboxId"); 231 | 232 | b.HasIndex("Created"); 233 | 234 | b.ToTable("outbox_state", "sample"); 235 | }); 236 | 237 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 238 | { 239 | b.Property("CorrelationId") 240 | .HasColumnType("uniqueidentifier") 241 | .HasColumnName("correlation_id"); 242 | 243 | b.Property("CurrentState") 244 | .HasColumnType("int") 245 | .HasColumnName("current_state"); 246 | 247 | b.Property("Faulted") 248 | .HasColumnType("datetime2") 249 | .HasColumnName("faulted"); 250 | 251 | b.Property("InstanceAddress") 252 | .HasColumnType("nvarchar(max)") 253 | .HasColumnName("instance_address"); 254 | 255 | b.Property("JobId") 256 | .HasColumnType("uniqueidentifier") 257 | .HasColumnName("job_id"); 258 | 259 | b.Property("RetryAttempt") 260 | .HasColumnType("int") 261 | .HasColumnName("retry_attempt"); 262 | 263 | b.Property("ServiceAddress") 264 | .HasColumnType("nvarchar(max)") 265 | .HasColumnName("service_address"); 266 | 267 | b.Property("Started") 268 | .HasColumnType("datetime2") 269 | .HasColumnName("started"); 270 | 271 | b.Property("StatusCheckTokenId") 272 | .HasColumnType("uniqueidentifier") 273 | .HasColumnName("status_check_token_id"); 274 | 275 | b.HasKey("CorrelationId"); 276 | 277 | b.HasIndex("JobId", "RetryAttempt") 278 | .IsUnique(); 279 | 280 | b.ToTable("job_attempt_saga", "sample"); 281 | }); 282 | 283 | modelBuilder.Entity("MassTransit.JobSaga", b => 284 | { 285 | b.Property("CorrelationId") 286 | .HasColumnType("uniqueidentifier") 287 | .HasColumnName("correlation_id"); 288 | 289 | b.Property("AttemptId") 290 | .HasColumnType("uniqueidentifier") 291 | .HasColumnName("attempt_id"); 292 | 293 | b.Property("Completed") 294 | .HasColumnType("datetime2") 295 | .HasColumnName("completed"); 296 | 297 | b.Property("CronExpression") 298 | .HasColumnType("nvarchar(max)") 299 | .HasColumnName("cron_expression"); 300 | 301 | b.Property("CurrentState") 302 | .HasColumnType("int") 303 | .HasColumnName("current_state"); 304 | 305 | b.Property("Duration") 306 | .HasColumnType("time") 307 | .HasColumnName("duration"); 308 | 309 | b.Property("EndDate") 310 | .HasColumnType("datetimeoffset") 311 | .HasColumnName("end_date"); 312 | 313 | b.Property("Faulted") 314 | .HasColumnType("datetime2") 315 | .HasColumnName("faulted"); 316 | 317 | b.Property("IncompleteAttempts") 318 | .HasColumnType("nvarchar(max)") 319 | .HasColumnName("incomplete_attempts"); 320 | 321 | b.Property("Job") 322 | .HasColumnType("nvarchar(max)") 323 | .HasColumnName("job"); 324 | 325 | b.Property("JobRetryDelayToken") 326 | .HasColumnType("uniqueidentifier") 327 | .HasColumnName("job_retry_delay_token"); 328 | 329 | b.Property("JobSlotWaitToken") 330 | .HasColumnType("uniqueidentifier") 331 | .HasColumnName("job_slot_wait_token"); 332 | 333 | b.Property("JobState") 334 | .HasColumnType("nvarchar(max)") 335 | .HasColumnName("job_state"); 336 | 337 | b.Property("JobTimeout") 338 | .HasColumnType("time") 339 | .HasColumnName("job_timeout"); 340 | 341 | b.Property("JobTypeId") 342 | .HasColumnType("uniqueidentifier") 343 | .HasColumnName("job_type_id"); 344 | 345 | b.Property("LastProgressLimit") 346 | .HasColumnType("bigint") 347 | .HasColumnName("last_progress_limit"); 348 | 349 | b.Property("LastProgressSequenceNumber") 350 | .HasColumnType("bigint") 351 | .HasColumnName("last_progress_sequence_number"); 352 | 353 | b.Property("LastProgressValue") 354 | .HasColumnType("bigint") 355 | .HasColumnName("last_progress_value"); 356 | 357 | b.Property("NextStartDate") 358 | .HasColumnType("datetimeoffset") 359 | .HasColumnName("next_start_date"); 360 | 361 | b.Property("Reason") 362 | .HasColumnType("nvarchar(max)") 363 | .HasColumnName("reason"); 364 | 365 | b.Property("RetryAttempt") 366 | .HasColumnType("int") 367 | .HasColumnName("retry_attempt"); 368 | 369 | b.Property("ServiceAddress") 370 | .HasColumnType("nvarchar(max)") 371 | .HasColumnName("service_address"); 372 | 373 | b.Property("StartDate") 374 | .HasColumnType("datetimeoffset") 375 | .HasColumnName("start_date"); 376 | 377 | b.Property("Started") 378 | .HasColumnType("datetime2") 379 | .HasColumnName("started"); 380 | 381 | b.Property("Submitted") 382 | .HasColumnType("datetime2") 383 | .HasColumnName("submitted"); 384 | 385 | b.Property("TimeZoneId") 386 | .HasColumnType("nvarchar(max)") 387 | .HasColumnName("time_zone_id"); 388 | 389 | b.HasKey("CorrelationId"); 390 | 391 | b.ToTable("job_saga", "sample"); 392 | }); 393 | 394 | modelBuilder.Entity("MassTransit.JobTypeSaga", b => 395 | { 396 | b.Property("CorrelationId") 397 | .HasColumnType("uniqueidentifier") 398 | .HasColumnName("correlation_id"); 399 | 400 | b.Property("ActiveJobCount") 401 | .HasColumnType("int") 402 | .HasColumnName("active_job_count"); 403 | 404 | b.Property("ActiveJobs") 405 | .HasColumnType("nvarchar(max)") 406 | .HasColumnName("active_jobs"); 407 | 408 | b.Property("ConcurrentJobLimit") 409 | .HasColumnType("int") 410 | .HasColumnName("concurrent_job_limit"); 411 | 412 | b.Property("CurrentState") 413 | .HasColumnType("int") 414 | .HasColumnName("current_state"); 415 | 416 | b.Property("GlobalConcurrentJobLimit") 417 | .HasColumnType("int") 418 | .HasColumnName("global_concurrent_job_limit"); 419 | 420 | b.Property("Instances") 421 | .HasColumnType("nvarchar(max)") 422 | .HasColumnName("instances"); 423 | 424 | b.Property("Name") 425 | .HasColumnType("nvarchar(max)") 426 | .HasColumnName("name"); 427 | 428 | b.Property("OverrideJobLimit") 429 | .HasColumnType("int") 430 | .HasColumnName("override_job_limit"); 431 | 432 | b.Property("OverrideLimitExpiration") 433 | .HasColumnType("datetime2") 434 | .HasColumnName("override_limit_expiration"); 435 | 436 | b.Property("Properties") 437 | .HasColumnType("nvarchar(max)") 438 | .HasColumnName("properties"); 439 | 440 | b.HasKey("CorrelationId"); 441 | 442 | b.ToTable("job_type_saga", "sample"); 443 | }); 444 | 445 | modelBuilder.Entity("Sample.Components.StateMachines.RegistrationState", b => 446 | { 447 | b.Property("CorrelationId") 448 | .HasColumnType("uniqueidentifier") 449 | .HasColumnName("correlation_id"); 450 | 451 | b.Property("CardNumber") 452 | .HasColumnType("nvarchar(max)") 453 | .HasColumnName("card_number"); 454 | 455 | b.Property("CurrentState") 456 | .HasColumnType("nvarchar(max)") 457 | .HasColumnName("current_state"); 458 | 459 | b.Property("EventId") 460 | .HasColumnType("nvarchar(max)") 461 | .HasColumnName("event_id"); 462 | 463 | b.Property("ParticipantCategory") 464 | .HasColumnType("nvarchar(max)") 465 | .HasColumnName("participant_category"); 466 | 467 | b.Property("ParticipantEmailAddress") 468 | .HasColumnType("nvarchar(max)") 469 | .HasColumnName("participant_email_address"); 470 | 471 | b.Property("ParticipantLicenseExpirationDate") 472 | .HasColumnType("datetime2") 473 | .HasColumnName("participant_license_expiration_date"); 474 | 475 | b.Property("ParticipantLicenseNumber") 476 | .HasColumnType("nvarchar(max)") 477 | .HasColumnName("participant_license_number"); 478 | 479 | b.Property("RaceId") 480 | .HasColumnType("nvarchar(max)") 481 | .HasColumnName("race_id"); 482 | 483 | b.Property("Reason") 484 | .HasColumnType("nvarchar(max)") 485 | .HasColumnName("reason"); 486 | 487 | b.Property("RegistrationId") 488 | .HasColumnType("uniqueidentifier") 489 | .HasColumnName("registration_id"); 490 | 491 | b.Property("RetryAttempt") 492 | .HasColumnType("int") 493 | .HasColumnName("retry_attempt"); 494 | 495 | b.Property("ScheduleRetryToken") 496 | .HasColumnType("uniqueidentifier") 497 | .HasColumnName("schedule_retry_token"); 498 | 499 | b.HasKey("CorrelationId"); 500 | 501 | b.ToTable("registration_state", "sample"); 502 | }); 503 | 504 | modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => 505 | { 506 | b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null) 507 | .WithMany() 508 | .HasForeignKey("OutboxId"); 509 | 510 | b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null) 511 | .WithMany() 512 | .HasForeignKey("InboxMessageId", "InboxConsumerId") 513 | .HasPrincipalKey("MessageId", "ConsumerId"); 514 | }); 515 | 516 | modelBuilder.Entity("MassTransit.JobAttemptSaga", b => 517 | { 518 | b.HasOne("MassTransit.JobSaga", null) 519 | .WithMany() 520 | .HasForeignKey("JobId") 521 | .OnDelete(DeleteBehavior.Cascade) 522 | .IsRequired(); 523 | }); 524 | #pragma warning restore 612, 618 525 | } 526 | } 527 | } 528 | --------------------------------------------------------------------------------