From 0bc18fdf1b01be43161185a7a338303dfa8b3ff0 Mon Sep 17 00:00:00 2001
From: Andreas Bednarz <110360248+abparticular@users.noreply.github.com>
Date: Thu, 13 Aug 2026 14:49:53 +1000
Subject: [PATCH] Initial implementation of
IExternalIntegrationRequestsDataStore
---
.../AuditQuery_Tests.cs | 1 -
...eControl.AcceptanceTests.PostgreSql.csproj | 3 +
...ceControl.AcceptanceTests.SqlServer.csproj | 3 +
...nalIntegrationDispatchRequests.Designer.cs | 892 ++++++++++++++++++
..._AddExternalIntegrationDispatchRequests.cs | 36 +
...SqlServiceControlDbContextModelSnapshot.cs | 26 +
...nalIntegrationDispatchRequests.Designer.cs | 716 ++++++++++++++
..._AddExternalIntegrationDispatchRequests.cs | 35 +
...verServiceControlDbContextModelSnapshot.cs | 22 +
.../EFPersistenceConfigurationBase.cs | 2 +
.../Abstractions/EFPersisterSettings.cs | 1 +
.../DbContexts/ServiceControlDbContext.cs | 2 +
...xternalIntegrationDispatchRequestEntity.cs | 11 +
...IntegrationDispatchRequestConfiguration.cs | 17 +
.../DispatchContextSerializer.cs | 33 +
.../ExternalIntegrationRequestsDataStore.cs | 216 ++++-
.../ExternalIntegrationRequestsDataStore.cs | 5 +-
.../EFCore/DispatchContextSerializerTests.cs | 65 ++
...rnalIntegrationRequestsDataStoreEFTests.cs | 115 +++
...ternalIntegrationRequestsDataStoreTests.cs | 122 +++
.../PersistenceTestBase.cs | 1 +
...IntegrationsServiceCollectionExtensions.cs | 7 +-
.../IntegrationEventWriter.cs | 19 +-
23 files changed, 2320 insertions(+), 30 deletions(-)
create mode 100644 src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.Designer.cs
create mode 100644 src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.cs
create mode 100644 src/ServiceControl.Persistence.EFCore.SqlServer/Migrations/20260811033208_AddExternalIntegrationDispatchRequests.Designer.cs
create mode 100644 src/ServiceControl.Persistence.EFCore.SqlServer/Migrations/20260811033208_AddExternalIntegrationDispatchRequests.cs
create mode 100644 src/ServiceControl.Persistence.EFCore/Entities/ExternalIntegrationDispatchRequestEntity.cs
create mode 100644 src/ServiceControl.Persistence.EFCore/EntityConfigurations/ExternalIntegrationDispatchRequestConfiguration.cs
create mode 100644 src/ServiceControl.Persistence.EFCore/Implementation/DispatchContextSerializer.cs
create mode 100644 src/ServiceControl.Persistence.Tests/EFCore/DispatchContextSerializerTests.cs
create mode 100644 src/ServiceControl.Persistence.Tests/EFCore/ExternalIntegrationRequestsDataStoreEFTests.cs
create mode 100644 src/ServiceControl.Persistence.Tests/ExternalIntegrationRequestsDataStoreTests.cs
diff --git a/src/Particular.LicensingComponent.UnitTests/AuditQuery_Tests.cs b/src/Particular.LicensingComponent.UnitTests/AuditQuery_Tests.cs
index b9318ecc88..19e0ccfa4c 100644
--- a/src/Particular.LicensingComponent.UnitTests/AuditQuery_Tests.cs
+++ b/src/Particular.LicensingComponent.UnitTests/AuditQuery_Tests.cs
@@ -6,7 +6,6 @@
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
-using Contracts;
using Microsoft.Extensions.Logging.Abstractions;
using NUnit.Framework;
using Particular.Approvals;
diff --git a/src/ServiceControl.AcceptanceTests.PostgreSql/ServiceControl.AcceptanceTests.PostgreSql.csproj b/src/ServiceControl.AcceptanceTests.PostgreSql/ServiceControl.AcceptanceTests.PostgreSql.csproj
index 74ed777f0b..451fa277b6 100644
--- a/src/ServiceControl.AcceptanceTests.PostgreSql/ServiceControl.AcceptanceTests.PostgreSql.csproj
+++ b/src/ServiceControl.AcceptanceTests.PostgreSql/ServiceControl.AcceptanceTests.PostgreSql.csproj
@@ -52,6 +52,9 @@
+
+
+
diff --git a/src/ServiceControl.AcceptanceTests.SqlServer/ServiceControl.AcceptanceTests.SqlServer.csproj b/src/ServiceControl.AcceptanceTests.SqlServer/ServiceControl.AcceptanceTests.SqlServer.csproj
index 5dda932f0e..48087c4e28 100644
--- a/src/ServiceControl.AcceptanceTests.SqlServer/ServiceControl.AcceptanceTests.SqlServer.csproj
+++ b/src/ServiceControl.AcceptanceTests.SqlServer/ServiceControl.AcceptanceTests.SqlServer.csproj
@@ -52,6 +52,9 @@
+
+
+
diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.Designer.cs b/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.Designer.cs
new file mode 100644
index 0000000000..03b08fcd64
--- /dev/null
+++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.Designer.cs
@@ -0,0 +1,892 @@
+//
+using System;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using ServiceControl.Persistence.EFCore.PostgreSql;
+
+#nullable disable
+
+namespace ServiceControl.Persistence.EFCore.PostgreSql.Migrations
+{
+ [DbContext(typeof(PostgreSqlServiceControlDbContext))]
+ [Migration("20260811033225_AddExternalIntegrationDispatchRequests")]
+ partial class AddExternalIntegrationDispatchRequests
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.10")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.ArchiveOperationEntity", b =>
+ {
+ b.Property("RequestId")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasColumnName("request_id");
+
+ b.Property("ArchiveType")
+ .HasColumnType("integer")
+ .HasColumnName("archive_type");
+
+ b.Property("OperationType")
+ .HasColumnType("integer")
+ .HasColumnName("operation_type");
+
+ b.Property("CurrentBatch")
+ .HasColumnType("integer")
+ .HasColumnName("current_batch");
+
+ b.Property("GroupName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("group_name");
+
+ b.Property("InitiatedById")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("initiated_by_id");
+
+ b.Property("InitiatedByName")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("initiated_by_name");
+
+ b.Property("NumberOfBatches")
+ .HasColumnType("integer")
+ .HasColumnName("number_of_batches");
+
+ b.Property("NumberOfMessagesProcessed")
+ .HasColumnType("integer")
+ .HasColumnName("number_of_messages_processed");
+
+ b.Property("OperationId")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("operation_id");
+
+ b.Property("Started")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("started");
+
+ b.Property("TotalNumberOfMessages")
+ .HasColumnType("integer")
+ .HasColumnName("total_number_of_messages");
+
+ b.HasKey("RequestId", "ArchiveType", "OperationType")
+ .HasName("pk_archive_operations");
+
+ b.HasIndex("Started")
+ .HasDatabaseName("ix_archive_operations_started");
+
+ b.ToTable("archive_operations", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.CustomCheckEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid")
+ .HasColumnName("id");
+
+ b.Property("Category")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("category");
+
+ b.Property("CustomCheckId")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("custom_check_id");
+
+ b.Property("FailureReason")
+ .HasColumnType("text")
+ .HasColumnName("failure_reason");
+
+ b.Property("OriginatingEndpointHost")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("originating_endpoint_host");
+
+ b.Property("OriginatingEndpointHostId")
+ .HasColumnType("uuid")
+ .HasColumnName("originating_endpoint_host_id");
+
+ b.Property("OriginatingEndpointName")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("originating_endpoint_name");
+
+ b.Property("ReportedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("reported_at");
+
+ b.Property("Status")
+ .HasColumnType("integer")
+ .HasColumnName("status");
+
+ b.HasKey("Id")
+ .HasName("pk_custom_checks");
+
+ b.HasIndex("ReportedAt")
+ .HasDatabaseName("ix_custom_checks_reported_at");
+
+ b.HasIndex("Status", "ReportedAt")
+ .HasDatabaseName("ix_custom_checks_status_reported_at");
+
+ b.ToTable("custom_checks", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.EndpointSettingsEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("name");
+
+ b.Property("TrackInstances")
+ .HasColumnType("boolean")
+ .HasColumnName("track_instances");
+
+ b.HasKey("Name")
+ .HasName("pk_endpoint_settings");
+
+ b.ToTable("endpoint_settings", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.EventLogItemEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Category")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("category");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("description");
+
+ b.Property("EventType")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("event_type");
+
+ b.Property("RaisedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("raised_at");
+
+ b.PrimitiveCollection>("RelatedTo")
+ .IsRequired()
+ .HasColumnType("text[]")
+ .HasColumnName("related_to");
+
+ b.Property("Severity")
+ .HasColumnType("integer")
+ .HasColumnName("severity");
+
+ b.HasKey("Id")
+ .HasName("pk_event_log_items");
+
+ b.HasIndex("RaisedAt", "Id")
+ .IsDescending()
+ .HasDatabaseName("ix_event_log_items_raised_at_id");
+
+ b.ToTable("EventLogItems", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.ExternalIntegrationDispatchRequestEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("DispatchContextJson")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("dispatch_context_json");
+
+ b.Property("DispatchContextTypeName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("dispatch_context_type_name");
+
+ b.HasKey("Id")
+ .HasName("pk_external_integration_dispatch_requests");
+
+ b.ToTable("ExternalIntegrationDispatchRequests", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedErrorImportEntity", b =>
+ {
+ b.Property("UniqueMessageId")
+ .HasColumnType("uuid")
+ .HasColumnName("unique_message_id");
+
+ b.Property("Body")
+ .IsRequired()
+ .HasColumnType("bytea")
+ .HasColumnName("body");
+
+ b.Property("BodyStoredExternally")
+ .HasColumnType("boolean")
+ .HasColumnName("body_stored_externally");
+
+ b.Property("ExceptionInfo")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("exception_info");
+
+ b.Property("FailedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("failed_at");
+
+ b.Property("HeadersJson")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("headers_json");
+
+ b.Property("MessageId")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("message_id");
+
+ b.HasKey("UniqueMessageId")
+ .HasName("pk_failed_error_imports");
+
+ b.HasIndex("FailedAt")
+ .HasDatabaseName("ix_failed_error_imports_failed_at");
+
+ b.ToTable("failed_error_imports", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageEntity", b =>
+ {
+ b.Property("UniqueMessageId")
+ .HasColumnType("uuid")
+ .HasColumnName("unique_message_id");
+
+ b.Property("BodyContentType")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("body_content_type");
+
+ b.Property("BodySize")
+ .HasColumnType("integer")
+ .HasColumnName("body_size");
+
+ b.Property("BodyStoredExternally")
+ .HasColumnType("boolean")
+ .HasColumnName("body_stored_externally");
+
+ b.Property("BodyText")
+ .HasColumnType("text")
+ .HasColumnName("body_text");
+
+ b.Property("ConversationId")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("conversation_id");
+
+ b.Property("ExceptionMessage")
+ .HasColumnType("text")
+ .HasColumnName("exception_message");
+
+ b.Property("ExceptionType")
+ .HasColumnType("text")
+ .HasColumnName("exception_type");
+
+ b.Property("FailingEndpointAddress")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("failing_endpoint_address");
+
+ b.Property("FirstTimeOfFailure")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("first_time_of_failure");
+
+ b.Property("HeadersJson")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("headers_json");
+
+ b.Property("IsSystemMessage")
+ .HasColumnType("boolean")
+ .HasColumnName("is_system_message");
+
+ b.Property("LastAttemptedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_attempted_at");
+
+ b.Property("LastModified")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_modified");
+
+ b.Property("LastTimeOfFailure")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_time_of_failure");
+
+ b.Property("MessageId")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("message_id");
+
+ b.Property("MessageType")
+ .HasColumnType("text")
+ .HasColumnName("message_type");
+
+ b.Property("NumberOfProcessingAttempts")
+ .HasColumnType("integer")
+ .HasColumnName("number_of_processing_attempts");
+
+ b.Property("ReceivingEndpointHost")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("receiving_endpoint_host");
+
+ b.Property("ReceivingEndpointHostId")
+ .HasColumnType("uuid")
+ .HasColumnName("receiving_endpoint_host_id");
+
+ b.Property("ReceivingEndpointName")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("receiving_endpoint_name");
+
+ b.Property("SendingEndpointHost")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("sending_endpoint_host");
+
+ b.Property("SendingEndpointHostId")
+ .HasColumnType("uuid")
+ .HasColumnName("sending_endpoint_host_id");
+
+ b.Property("SendingEndpointName")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("sending_endpoint_name");
+
+ b.Property("Status")
+ .HasColumnType("integer")
+ .HasColumnName("status");
+
+ b.Property("StatusChangedAt")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("status_changed_at");
+
+ b.Property("TimeSent")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("time_sent");
+
+ b.HasKey("UniqueMessageId")
+ .HasName("pk_failed_messages");
+
+ b.HasIndex("ConversationId")
+ .HasDatabaseName("ix_failed_messages_conversation_id");
+
+ b.HasIndex("FailingEndpointAddress")
+ .HasDatabaseName("ix_failed_messages_failing_endpoint_address");
+
+ b.HasIndex("ReceivingEndpointName")
+ .HasDatabaseName("ix_failed_messages_receiving_endpoint_name");
+
+ b.HasIndex("StatusChangedAt")
+ .HasDatabaseName("ix_failed_messages_status_changed_at")
+ .HasFilter("status IN (2, 4)");
+
+ b.HasIndex("TimeSent")
+ .HasDatabaseName("ix_failed_messages_time_sent");
+
+ b.HasIndex("Status", "LastModified")
+ .HasDatabaseName("ix_failed_messages_status_last_modified");
+
+ b.ToTable("failed_messages", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageGroupEntity", b =>
+ {
+ b.Property("FailedMessageUniqueId")
+ .HasColumnType("uuid")
+ .HasColumnName("failed_message_unique_id");
+
+ b.Property("GroupId")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasColumnName("group_id");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("title");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("character varying(255)")
+ .HasColumnName("type");
+
+ b.HasKey("FailedMessageUniqueId", "GroupId")
+ .HasName("pk_failed_message_groups");
+
+ b.HasIndex("GroupId")
+ .HasDatabaseName("ix_failed_message_groups_group_id");
+
+ b.HasIndex("Type", "GroupId")
+ .HasDatabaseName("ix_failed_message_groups_type_group_id");
+
+ b.ToTable("failed_message_groups", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageRetryEntity", b =>
+ {
+ b.Property("UniqueMessageId")
+ .HasColumnType("uuid")
+ .HasColumnName("unique_message_id");
+
+ b.Property("RetryBatchId")
+ .HasColumnType("uuid")
+ .HasColumnName("retry_batch_id");
+
+ b.Property("StageAttempts")
+ .HasColumnType("integer")
+ .HasColumnName("stage_attempts");
+
+ b.HasKey("UniqueMessageId")
+ .HasName("pk_failed_message_retries");
+
+ b.HasIndex("RetryBatchId")
+ .HasDatabaseName("ix_failed_message_retries_retry_batch_id");
+
+ b.ToTable("failed_message_retries", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.GroupCommentEntity", b =>
+ {
+ b.Property("GroupId")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)")
+ .HasColumnName("group_id");
+
+ b.Property("Comment")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("comment");
+
+ b.HasKey("GroupId")
+ .HasName("pk_group_comments");
+
+ b.ToTable("group_comments", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.HistoricRetryOperationEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("CompletionTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("completion_time");
+
+ b.Property("Failed")
+ .HasColumnType("boolean")
+ .HasColumnName("failed");
+
+ b.Property("NumberOfMessagesProcessed")
+ .HasColumnType("integer")
+ .HasColumnName("number_of_messages_processed");
+
+ b.Property("Originator")
+ .HasColumnType("text")
+ .HasColumnName("originator");
+
+ b.Property("RequestId")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("character varying(400)")
+ .HasColumnName("request_id");
+
+ b.Property("RetryType")
+ .HasColumnType("integer")
+ .HasColumnName("retry_type");
+
+ b.Property("StartTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("start_time");
+
+ b.HasKey("Id")
+ .HasName("pk_historic_retry_operations");
+
+ b.HasIndex("CompletionTime", "Id")
+ .IsDescending()
+ .HasDatabaseName("ix_historic_retry_operations_completion_time_id");
+
+ b.ToTable("historic_retry_operations", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.KnownEndpointEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid")
+ .HasColumnName("id");
+
+ b.Property("Host")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("host");
+
+ b.Property("HostId")
+ .HasColumnType("uuid")
+ .HasColumnName("host_id");
+
+ b.Property("Monitored")
+ .HasColumnType("boolean")
+ .HasColumnName("monitored");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("name");
+
+ b.HasKey("Id")
+ .HasName("pk_known_endpoints");
+
+ b.ToTable("known_endpoints", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.LicensingEndpointEntity", b =>
+ {
+ b.Property("NormalizedName")
+ .HasMaxLength(300)
+ .HasColumnType("character varying(300)")
+ .HasColumnName("normalized_name");
+
+ b.Property("ThroughputSource")
+ .HasColumnType("integer")
+ .HasColumnName("throughput_source");
+
+ b.PrimitiveCollection>("EndpointIndicators")
+ .IsRequired()
+ .HasColumnType("text[]")
+ .HasColumnName("endpoint_indicators");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(300)
+ .HasColumnType("character varying(300)")
+ .HasColumnName("name");
+
+ b.Property("NormalizedSanitizedName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("normalized_sanitized_name");
+
+ b.Property("SanitizedName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("sanitized_name");
+
+ b.Property("Scope")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("scope");
+
+ b.Property("UserIndicator")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("user_indicator");
+
+ b.HasKey("NormalizedName", "ThroughputSource")
+ .HasName("pk_licensing_endpoints");
+
+ b.HasIndex("NormalizedSanitizedName")
+ .HasDatabaseName("ix_licensing_endpoints_normalized_sanitized_name");
+
+ b.ToTable("licensing_endpoints", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.LicensingEndpointThroughputEntity", b =>
+ {
+ b.Property("NormalizedName")
+ .HasMaxLength(300)
+ .HasColumnType("character varying(300)")
+ .HasColumnName("normalized_name");
+
+ b.Property("ThroughputSource")
+ .HasColumnType("integer")
+ .HasColumnName("throughput_source");
+
+ b.Property("DateUtc")
+ .HasColumnType("date")
+ .HasColumnName("date_utc");
+
+ b.Property("MessageCount")
+ .HasColumnType("bigint")
+ .HasColumnName("message_count");
+
+ b.HasKey("NormalizedName", "ThroughputSource", "DateUtc")
+ .HasName("pk_licensing_endpoint_throughput");
+
+ b.HasIndex("DateUtc")
+ .HasDatabaseName("ix_licensing_endpoint_throughput_date_utc");
+
+ b.ToTable("licensing_endpoint_throughput", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.MessageRedirectEntity", b =>
+ {
+ b.Property("FromPhysicalAddress")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("from_physical_address");
+
+ b.Property("LastModified")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last_modified");
+
+ b.Property("ToPhysicalAddress")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("to_physical_address");
+
+ b.HasKey("FromPhysicalAddress")
+ .HasName("pk_message_redirects");
+
+ b.ToTable("message_redirects", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.RetryBatchEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uuid")
+ .HasColumnName("id");
+
+ b.Property("Classifier")
+ .HasColumnType("text")
+ .HasColumnName("classifier");
+
+ b.Property("Context")
+ .HasColumnType("text")
+ .HasColumnName("context");
+
+ b.Property("InitialBatchSize")
+ .HasColumnType("integer")
+ .HasColumnName("initial_batch_size");
+
+ b.Property("InitiatedById")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("initiated_by_id");
+
+ b.Property("InitiatedByName")
+ .HasColumnType("text")
+ .HasColumnName("initiated_by_name");
+
+ b.Property("Last")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last");
+
+ b.Property("OperationId")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("operation_id");
+
+ b.Property("Originator")
+ .HasColumnType("text")
+ .HasColumnName("originator");
+
+ b.Property("RequestId")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("request_id");
+
+ b.Property("RetrySessionId")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("retry_session_id");
+
+ b.Property("RetryType")
+ .HasColumnType("integer")
+ .HasColumnName("retry_type");
+
+ b.Property("StagingId")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("staging_id");
+
+ b.Property("StartTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("start_time");
+
+ b.Property("Status")
+ .HasColumnType("integer")
+ .HasColumnName("status");
+
+ b.HasKey("Id")
+ .HasName("pk_retry_batches");
+
+ b.HasIndex("Status", "RetrySessionId")
+ .HasDatabaseName("ix_retry_batches_status_retry_session_id");
+
+ b.ToTable("retry_batches", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.RetryBatchNowForwardingEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("integer")
+ .HasColumnName("id");
+
+ b.Property("RetryBatchId")
+ .HasColumnType("uuid")
+ .HasColumnName("retry_batch_id");
+
+ b.HasKey("Id")
+ .HasName("pk_retry_batch_now_forwarding");
+
+ b.ToTable("retry_batch_now_forwarding", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.SettingEntity", b =>
+ {
+ b.Property("Key")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("key");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("value");
+
+ b.HasKey("Key")
+ .HasName("pk_settings");
+
+ b.ToTable("settings", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.SubscriptionEntity", b =>
+ {
+ b.Property("MessageType")
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("message_type");
+
+ b.Property("TransportAddress")
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("transport_address");
+
+ b.Property("Endpoint")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("endpoint");
+
+ b.HasKey("MessageType", "TransportAddress")
+ .HasName("pk_subscriptions");
+
+ b.ToTable("subscriptions", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.UnacknowledgedRetryOperationEntity", b =>
+ {
+ b.Property("RequestId")
+ .HasMaxLength(400)
+ .HasColumnType("character varying(400)")
+ .HasColumnName("request_id");
+
+ b.Property("RetryType")
+ .HasColumnType("integer")
+ .HasColumnName("retry_type");
+
+ b.Property("Classifier")
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("classifier");
+
+ b.Property("CompletionTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("completion_time");
+
+ b.Property("Failed")
+ .HasColumnType("boolean")
+ .HasColumnName("failed");
+
+ b.Property("Last")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("last");
+
+ b.Property("NumberOfMessagesProcessed")
+ .HasColumnType("integer")
+ .HasColumnName("number_of_messages_processed");
+
+ b.Property("Originator")
+ .HasColumnType("text")
+ .HasColumnName("originator");
+
+ b.Property("StartTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("start_time");
+
+ b.HasKey("RequestId", "RetryType")
+ .HasName("pk_unacknowledged_retry_operations");
+
+ b.ToTable("unacknowledged_retry_operations", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageGroupEntity", b =>
+ {
+ b.HasOne("ServiceControl.Persistence.EFCore.Entities.FailedMessageEntity", null)
+ .WithMany()
+ .HasForeignKey("FailedMessageUniqueId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("fk_failed_message_groups_failed_messages_failed_message_unique");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.LicensingEndpointThroughputEntity", b =>
+ {
+ b.HasOne("ServiceControl.Persistence.EFCore.Entities.LicensingEndpointEntity", null)
+ .WithMany()
+ .HasForeignKey("NormalizedName", "ThroughputSource")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("fk_licensing_endpoint_throughput_licensing_endpoints_normalize");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.cs b/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.cs
new file mode 100644
index 0000000000..21e999c399
--- /dev/null
+++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/20260811033225_AddExternalIntegrationDispatchRequests.cs
@@ -0,0 +1,36 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace ServiceControl.Persistence.EFCore.PostgreSql.Migrations
+{
+ ///
+ public partial class AddExternalIntegrationDispatchRequests : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "ExternalIntegrationDispatchRequests",
+ columns: table => new
+ {
+ id = table.Column(type: "bigint", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ dispatch_context_type_name = table.Column(type: "character varying(450)", maxLength: 450, nullable: false),
+ dispatch_context_json = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("pk_external_integration_dispatch_requests", x => x.id);
+ });
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "ExternalIntegrationDispatchRequests");
+ }
+ }
+}
diff --git a/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/PostgreSqlServiceControlDbContextModelSnapshot.cs b/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/PostgreSqlServiceControlDbContextModelSnapshot.cs
index 2d746723fd..8b70bfa65c 100644
--- a/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/PostgreSqlServiceControlDbContextModelSnapshot.cs
+++ b/src/ServiceControl.Persistence.EFCore.PostgreSql/Migrations/PostgreSqlServiceControlDbContextModelSnapshot.cs
@@ -207,6 +207,32 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("EventLogItems", (string)null);
});
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.ExternalIntegrationDispatchRequestEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("DispatchContextJson")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("dispatch_context_json");
+
+ b.Property("DispatchContextTypeName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("character varying(450)")
+ .HasColumnName("dispatch_context_type_name");
+
+ b.HasKey("Id")
+ .HasName("pk_external_integration_dispatch_requests");
+
+ b.ToTable("ExternalIntegrationDispatchRequests", (string)null);
+ });
+
modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedErrorImportEntity", b =>
{
b.Property("UniqueMessageId")
diff --git a/src/ServiceControl.Persistence.EFCore.SqlServer/Migrations/20260811033208_AddExternalIntegrationDispatchRequests.Designer.cs b/src/ServiceControl.Persistence.EFCore.SqlServer/Migrations/20260811033208_AddExternalIntegrationDispatchRequests.Designer.cs
new file mode 100644
index 0000000000..f504489855
--- /dev/null
+++ b/src/ServiceControl.Persistence.EFCore.SqlServer/Migrations/20260811033208_AddExternalIntegrationDispatchRequests.Designer.cs
@@ -0,0 +1,716 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using ServiceControl.Persistence.EFCore.SqlServer;
+
+#nullable disable
+
+namespace ServiceControl.Persistence.EFCore.SqlServer.Migrations
+{
+ [DbContext(typeof(SqlServerServiceControlDbContext))]
+ [Migration("20260811033208_AddExternalIntegrationDispatchRequests")]
+ partial class AddExternalIntegrationDispatchRequests
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.10")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.ArchiveOperationEntity", b =>
+ {
+ b.Property("RequestId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ArchiveType")
+ .HasColumnType("int");
+
+ b.Property("OperationType")
+ .HasColumnType("int");
+
+ b.Property("CurrentBatch")
+ .HasColumnType("int");
+
+ b.Property("GroupName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("InitiatedById")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("InitiatedByName")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("NumberOfBatches")
+ .HasColumnType("int");
+
+ b.Property("NumberOfMessagesProcessed")
+ .HasColumnType("int");
+
+ b.Property("OperationId")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Started")
+ .HasColumnType("datetime2");
+
+ b.Property("TotalNumberOfMessages")
+ .HasColumnType("int");
+
+ b.HasKey("RequestId", "ArchiveType", "OperationType");
+
+ b.HasIndex("Started");
+
+ b.ToTable("ArchiveOperations");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.CustomCheckEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Category")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CustomCheckId")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("FailureReason")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("OriginatingEndpointHost")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("OriginatingEndpointHostId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("OriginatingEndpointName")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ReportedAt")
+ .HasColumnType("datetime2");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ReportedAt");
+
+ b.HasIndex("Status", "ReportedAt");
+
+ b.ToTable("CustomChecks");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.EndpointSettingsEntity", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("TrackInstances")
+ .HasColumnType("bit");
+
+ b.HasKey("Name");
+
+ b.ToTable("EndpointSettings");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.EventLogItemEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Category")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("EventType")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("RaisedAt")
+ .HasColumnType("datetime2");
+
+ b.PrimitiveCollection("RelatedTo")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Severity")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RaisedAt", "Id")
+ .IsDescending();
+
+ b.ToTable("EventLogItems", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.ExternalIntegrationDispatchRequestEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("DispatchContextJson")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("DispatchContextTypeName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.HasKey("Id");
+
+ b.ToTable("ExternalIntegrationDispatchRequests", (string)null);
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedErrorImportEntity", b =>
+ {
+ b.Property("UniqueMessageId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Body")
+ .IsRequired()
+ .HasColumnType("varbinary(max)");
+
+ b.Property("BodyStoredExternally")
+ .HasColumnType("bit");
+
+ b.Property("ExceptionInfo")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("FailedAt")
+ .HasColumnType("datetime2");
+
+ b.Property("HeadersJson")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("MessageId")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.HasKey("UniqueMessageId");
+
+ b.HasIndex("FailedAt");
+
+ b.ToTable("FailedErrorImports");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageEntity", b =>
+ {
+ b.Property("UniqueMessageId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("BodyContentType")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("BodySize")
+ .HasColumnType("int");
+
+ b.Property("BodyStoredExternally")
+ .HasColumnType("bit");
+
+ b.Property("BodyText")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ConversationId")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("ExceptionMessage")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ExceptionType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("FailingEndpointAddress")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("FirstTimeOfFailure")
+ .HasColumnType("datetime2");
+
+ b.Property("HeadersJson")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsSystemMessage")
+ .HasColumnType("bit");
+
+ b.Property("LastAttemptedAt")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModified")
+ .HasColumnType("datetime2");
+
+ b.Property("LastTimeOfFailure")
+ .HasColumnType("datetime2");
+
+ b.Property("MessageId")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("MessageType")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("NumberOfProcessingAttempts")
+ .HasColumnType("int");
+
+ b.Property("ReceivingEndpointHost")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("ReceivingEndpointHostId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ReceivingEndpointName")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("SendingEndpointHost")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("SendingEndpointHostId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SendingEndpointName")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Status")
+ .HasColumnType("int");
+
+ b.Property("StatusChangedAt")
+ .HasColumnType("datetime2");
+
+ b.Property("TimeSent")
+ .HasColumnType("datetime2");
+
+ b.HasKey("UniqueMessageId");
+
+ b.HasIndex("ConversationId");
+
+ b.HasIndex("FailingEndpointAddress");
+
+ b.HasIndex("ReceivingEndpointName");
+
+ b.HasIndex("StatusChangedAt")
+ .HasFilter("[Status] IN (2, 4)");
+
+ b.HasIndex("TimeSent");
+
+ b.HasIndex("Status", "LastModified");
+
+ b.ToTable("FailedMessages");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageGroupEntity", b =>
+ {
+ b.Property("FailedMessageUniqueId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("GroupId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("nvarchar(255)");
+
+ b.HasKey("FailedMessageUniqueId", "GroupId");
+
+ b.HasIndex("GroupId");
+
+ b.HasIndex("Type", "GroupId");
+
+ b.ToTable("FailedMessageGroups");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.FailedMessageRetryEntity", b =>
+ {
+ b.Property("UniqueMessageId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("RetryBatchId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("StageAttempts")
+ .HasColumnType("int");
+
+ b.HasKey("UniqueMessageId");
+
+ b.HasIndex("RetryBatchId");
+
+ b.ToTable("FailedMessageRetries");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.GroupCommentEntity", b =>
+ {
+ b.Property("GroupId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("Comment")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("GroupId");
+
+ b.ToTable("GroupComments");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.HistoricRetryOperationEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("CompletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Failed")
+ .HasColumnType("bit");
+
+ b.Property("NumberOfMessagesProcessed")
+ .HasColumnType("int");
+
+ b.Property("Originator")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("RequestId")
+ .IsRequired()
+ .HasMaxLength(400)
+ .HasColumnType("nvarchar(400)");
+
+ b.Property("RetryType")
+ .HasColumnType("int");
+
+ b.Property("StartTime")
+ .HasColumnType("datetime2");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CompletionTime", "Id")
+ .IsDescending();
+
+ b.ToTable("HistoricRetryOperations");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.KnownEndpointEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Host")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("HostId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Monitored")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.HasKey("Id");
+
+ b.ToTable("KnownEndpoints");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.LicensingEndpointEntity", b =>
+ {
+ b.Property("NormalizedName")
+ .HasMaxLength(300)
+ .HasColumnType("nvarchar(300)");
+
+ b.Property("ThroughputSource")
+ .HasColumnType("int");
+
+ b.PrimitiveCollection("EndpointIndicators")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(300)
+ .HasColumnType("nvarchar(300)");
+
+ b.Property("NormalizedSanitizedName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("SanitizedName")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("Scope")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("UserIndicator")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.HasKey("NormalizedName", "ThroughputSource");
+
+ b.HasIndex("NormalizedSanitizedName");
+
+ b.ToTable("LicensingEndpoints");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.LicensingEndpointThroughputEntity", b =>
+ {
+ b.Property("NormalizedName")
+ .HasMaxLength(300)
+ .HasColumnType("nvarchar(300)");
+
+ b.Property("ThroughputSource")
+ .HasColumnType("int");
+
+ b.Property("DateUtc")
+ .HasColumnType("date");
+
+ b.Property("MessageCount")
+ .HasColumnType("bigint");
+
+ b.HasKey("NormalizedName", "ThroughputSource", "DateUtc");
+
+ b.HasIndex("DateUtc");
+
+ b.ToTable("LicensingEndpointThroughput");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.MessageRedirectEntity", b =>
+ {
+ b.Property("FromPhysicalAddress")
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.Property("LastModified")
+ .HasColumnType("datetime2");
+
+ b.Property("ToPhysicalAddress")
+ .IsRequired()
+ .HasMaxLength(450)
+ .HasColumnType("nvarchar(450)");
+
+ b.HasKey("FromPhysicalAddress");
+
+ b.ToTable("MessageRedirects");
+ });
+
+ modelBuilder.Entity("ServiceControl.Persistence.EFCore.Entities.RetryBatchEntity", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property