Skip to content

Commit 3f0261f

Browse files
jpalacSzymonPobiegaPhilBastianandreasohlund
authored
Add support for PostgreSQL Transport (#4443)
* Bring sqlserver files in line with sqlserver transport to avoid confusion in naming * First changes for PostgreSql transport * nullable fix * test fix * manifest file test fix * Added test project * Do some random work on postgresql support - Update query for current sequence value - Update addressing types - Update query for estimating queue length * build fix * fix setting value key * remove unused code * customise queue names with schema for postgres when provisioning queues * added todo for something that errors * removed commented out code * connection validator for postgres * Fix subscription table parameter for postgresql * fix test * Translate transport sending queues in instances * fix test * Change ToTransportQualifiedQueueNameCore to use double quotes * use postgres customisation for error queue names * alternative to get latest identity value for table that doesn't rely on current session increment * revert double assigning of schema * Use new alpha of the transport with fixed delay bug * Add connection string default * Translate queue names when using dispatcher directly in tests * fix query to work with postgres syntax * fix syntax issues (functionality still broken) * fix RunScenario test * Translate queues for forwarding message in Audit and Error ingestion * attempt to get postgres running on ci * added test category for psotgres * update postgres env variable * reverting app.config changes * clarify not using nolock * update connection string name so it matches existing ones * Perform az login for postgres * fix error catching on failed connection * fix sqlserver tests * query fix * Fix indicator update for transports that display endpointname on SP, ie slq server and postgresql * Translate throughput queue for sending from monitoring * fix extra character * Add test for throughput fix * Cleanup * Avoid translating audit log queue multiple times * Avoid translating multiple times when reporting throughput * Avoid translating error log queue multiple times * Remove message driven pubsub comment * Fix bad merge * More bad merge fixes * Formatting * translate staging queue * fix dequeue tests * variable name cleanup + add ability to quote subscription table * Run container tests for postgres * Fix docker command * Use compose file to run postgres * Fix container name * Fix pwd * Fix service deps * Skip volume * Add health check * use default username and database * Revert pool size * Remove unneded settings * limit postgreSQL connections for monitoring and audit to prevent connection starvation * fix rebase * fix null reference in tests * more test fixing * change name of default max concurrency level properties and apply to sql server transport * fix CI test * revert changes to SQL server max connections defaults * Decrease the queue lenght read frequency for SQL Server and PostgreSQL * Update to Postgres transport 8.1.4 * Update src/ServiceControl.Transports.PostgreSql/transport.manifest * fix from rebase * reapply change lost in rebase * reapply change lost in rebase --------- Co-authored-by: SzymonPobiega <szymon.pobiega@gmail.com> Co-authored-by: Phil Bastian <phil.bastian@particular.net> Co-authored-by: Andreas Öhlund <andreas.ohlund@particular.net>
1 parent f36ddbc commit 3f0261f

File tree

82 files changed

+1331
-127
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1331
-127
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
matrix:
1717
os: [windows-2022, ubuntu-22.04]
18-
test-category: [ Default, SqlServer, AzureServiceBus, RabbitMQ, AzureStorageQueues, MSMQ, SQS, PrimaryRavenAcceptance, PrimaryRavenPersistence ]
18+
test-category: [ Default, SqlServer, AzureServiceBus, RabbitMQ, AzureStorageQueues, MSMQ, SQS, PrimaryRavenAcceptance, PrimaryRavenPersistence, PostgreSQL ]
1919
include:
2020
- os: windows-2022
2121
os-name: Windows
@@ -65,7 +65,7 @@ jobs:
6565
run: Import-Module ./deploy/PowerShellModules/Particular.ServiceControl.Management
6666
- name: Azure login
6767
uses: azure/login@v2.2.0
68-
if: matrix.test-category == 'AzureServiceBus' || matrix.test-category == 'AzureStorageQueues' || matrix.test-category == 'RabbitMQ'
68+
if: matrix.test-category == 'AzureServiceBus' || matrix.test-category == 'AzureStorageQueues' || matrix.test-category == 'RabbitMQ' || matrix.test-category == 'PostgreSQL'
6969
with:
7070
creds: ${{ secrets.AZURE_ACI_CREDENTIALS }}
7171
- name: Setup SQL Server
@@ -74,6 +74,14 @@ jobs:
7474
with:
7575
connection-string-env-var: ServiceControl_TransportTests_SQL_ConnectionString
7676
catalog: nservicebus
77+
- name: Setup PostgreSQL
78+
uses: Particular/setup-postgres-action@v1.0.0
79+
if: matrix.test-category == 'PostgreSQL'
80+
with:
81+
connection-string-name: ServiceControl_TransportTests_PostgreSQL_ConnectionString
82+
tag: ServiceControl
83+
registry-username: ${{ secrets.DOCKERHUB_USERNAME }}
84+
registry-password: ${{ secrets.DOCKERHUB_TOKEN }}
7785
- name: Setup RabbitMQ
7886
uses: Particular/setup-rabbitmq-action@v1.7.0
7987
if: matrix.test-category == 'RabbitMQ'

.github/workflows/container-integration-test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ jobs:
2222
connection-string: 'Server=mssql;Database=master;User=sa;Password=ServiceControl1!;Encrypt=False;'
2323
compose-cmd: docker compose -f servicecontrol.yml -f mssql.yml up -d
2424
expected-healthy-containers: 5
25+
- name: postgresql
26+
transport: PostgreSQL
27+
connection-string: 'Host=postgres;Port=5432;Database=postgres;User ID=postgres;Password=ServiceControl1!;'
28+
compose-cmd: docker compose -f servicecontrol.yml -f postgres.yml up -d
29+
expected-healthy-containers: 5
2530
- name: asb
2631
transport: NetStandardAzureServiceBus
2732
compose-cmd: docker compose -f servicecontrol.yml up -d

src/Directory.Packages.props

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@
4646
<PackageVersion Include="NServiceBus.Transport.AzureServiceBus" Version="4.2.2" />
4747
<PackageVersion Include="NServiceBus.Transport.AzureStorageQueues" Version="13.0.1" />
4848
<PackageVersion Include="NServiceBus.Transport.Msmq.Sources" Version="3.0.1" />
49-
<PackageVersion Include="NServiceBus.Transport.SqlServer" Version="8.1.3" />
50-
<PackageVersion Include="NuGet.Versioning" Version="6.11.0" />
49+
<PackageVersion Include="NServiceBus.Transport.SqlServer" Version="8.1.4" />
50+
<PackageVersion Include="NServiceBus.Transport.PostgreSql" Version="8.1.4" />
51+
<PackageVersion Include="Npgsql" Version="8.0.3" />
52+
<PackageVersion Include="NuGet.Versioning" Version="6.11.0" />
5153
<PackageVersion Include="NUnit" Version="4.2.2" />
5254
<PackageVersion Include="NUnit.Analyzers" Version="4.3.0" />
5355
<PackageVersion Include="NUnit3TestAdapter" Version="4.6.0" />

src/Particular.LicensingComponent.Persistence.InMemory/InMemoryLicensingDataStore.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,13 @@ public async Task UpdateUserIndicatorOnEndpoints(List<UpdateUserIndicator> userI
117117
//if there are multiple sources of throughput for the endpoint, update them all
118118
var existingEndpoints = GetAllConnectedEndpoints(e.Name);
119119

120-
existingEndpoints.ForEach(u => u.UserIndicator = e.UserIndicator);
120+
existingEndpoints.ForEach(u =>
121+
{
122+
u.UserIndicator = e.UserIndicator;
123+
//for ones that matched on endpoint name, update matching on sanitizedName
124+
var sanitizedMAtchingEndpoints = GetAllConnectedEndpoints(u.SanitizedName);
125+
sanitizedMAtchingEndpoints.ForEach(s => s.UserIndicator = e.UserIndicator);
126+
});
121127
});
122128

123129
await Task.CompletedTask;
@@ -138,7 +144,7 @@ public async Task<bool> IsThereThroughputForLastXDaysForSource(int days, Through
138144
endpointThroughput.Value.Any(t => t.Key >= DateOnly.FromDateTime(DateTime.UtcNow).AddDays(-days) && t.Key <= endDate)));
139145
}
140146

141-
List<Endpoint> GetAllConnectedEndpoints(string name) => endpoints.Where(w => w.SanitizedName == name).ToList();
147+
List<Endpoint> GetAllConnectedEndpoints(string name) => endpoints.Where(w => w.SanitizedName == name || w.Id.Name == name).ToList();
142148

143149
public Task<BrokerMetadata> GetBrokerMetadata(CancellationToken cancellationToken) => Task.FromResult(brokerMetadata);
144150

src/ProjectReferences.Transports.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<ProjectReference Include="..\ServiceControl.Transports.Msmq\ServiceControl.Transports.Msmq.csproj" ReferenceOutputAssembly="false" Private="false" SkipGetTargetFrameworkProperties="true" UndefineProperties="TargetFramework" />
88
<ProjectReference Include="..\ServiceControl.Transports.RabbitMQ\ServiceControl.Transports.RabbitMQ.csproj" ReferenceOutputAssembly="false" Private="false" />
99
<ProjectReference Include="..\ServiceControl.Transports.SqlServer\ServiceControl.Transports.SqlServer.csproj" ReferenceOutputAssembly="false" Private="false" />
10+
<ProjectReference Include="..\ServiceControl.Transports.PostgreSql\ServiceControl.Transports.PostgreSql.csproj" ReferenceOutputAssembly="false" Private="false" />
1011
<ProjectReference Include="..\ServiceControl.Transports.SQS\ServiceControl.Transports.SQS.csproj" ReferenceOutputAssembly="false" Private="false" />
1112
</ItemGroup>
1213

src/ServiceControl.AcceptanceTests.RavenDB/StartupModeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public async Task InitializeSettings()
2424
var transportIntegration = new ConfigureEndpointLearningTransport();
2525

2626
settings = new Settings(
27+
transportType: transportIntegration.TypeName,
2728
forwardErrorMessages: false,
2829
errorRetentionPeriod: TimeSpan.FromDays(1),
2930
persisterType: "RavenDB")
3031
{
31-
TransportType = transportIntegration.TypeName,
3232
TransportConnectionString = transportIntegration.ConnectionString,
3333
AssemblyLoadContextResolver = static _ => AssemblyLoadContext.Default
3434
};

src/ServiceControl.Audit.UnitTests/Infrastructure/When_instance_is_setup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,6 @@ public Task<TransportInfrastructure> CreateTransportInfrastructure(string name,
8888
OnError onError = null, Func<string, Exception, Task> onCriticalError = null,
8989
TransportTransactionMode preferredTransactionMode = TransportTransactionMode.ReceiveOnly) =>
9090
throw new NotImplementedException();
91+
public string ToTransportQualifiedQueueName(string queueName) => queueName;
9192
}
9293
}

src/ServiceControl.Audit/App.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ These settings are only here so that we can debug ServiceControl while developin
1717
<!--<add key="ServiceControl.Audit/TransportType" value="NetStandardAzureServiceBus" />-->
1818
<!--<add key="ServiceControl.Audit/TransportType" value="RabbitMQ.QuorumConventionalRouting" />-->
1919
<!--<add key="ServiceControl.Audit/TransportType" value="SQLServer" />-->
20+
<!--<add key="ServiceControl.Audit/TransportType" value="PostgreSQL" />-->
2021

2122
<!-- DEVS - Pick a persistence to run Auditing instance on. -->
2223
<add key="ServiceControl.Audit/PersistenceType" value="InMemory" />
@@ -46,5 +47,8 @@ These settings are only here so that we can debug ServiceControl while developin
4647

4748
<!--SQLServer -->
4849
<!--<add name="NServiceBus/Transport" connectionString="Data Source=;Initial Catalog=nservicebus;Integrated Security=True;Queue Schema=myschema;Subscriptions Table=tablename@schema@catalog" />-->
50+
51+
<!--PostgreSQL -->
52+
<!--<add name="NServiceBus/Transport" connectionString="Server=;Database=nservicebus;Port=5432;User Id=;Password=;" />-->
4953
</connectionStrings>
5054
</configuration>

src/ServiceControl.Audit/Auditing/AuditIngestor.cs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@
1515
using Recoverability;
1616
using SagaAudit;
1717
using ServiceControl.Infrastructure.Metrics;
18+
using ServiceControl.Transports;
1819

1920
public class AuditIngestor
2021
{
21-
static readonly long FrequencyInMilliseconds = Stopwatch.Frequency / 1000;
22-
2322
public AuditIngestor(
2423
Metrics metrics,
2524
Settings settings,
2625
IAuditIngestionUnitOfWorkFactory unitOfWorkFactory,
2726
EndpointInstanceMonitoring endpointInstanceMonitoring,
2827
IEnumerable<IEnrichImportedAuditMessages> auditEnrichers, // allows extending message enrichers with custom enrichers registered in the DI container
2928
IMessageSession messageSession,
30-
Lazy<IMessageDispatcher> messageDispatcher
29+
Lazy<IMessageDispatcher> messageDispatcher,
30+
ITransportCustomization transportCustomization
3131
)
3232
{
3333
this.settings = settings;
@@ -49,14 +49,16 @@ Lazy<IMessageDispatcher> messageDispatcher
4949
new SagaRelationshipsEnricher()
5050
}.Concat(auditEnrichers).ToArray();
5151

52+
logQueueAddress = transportCustomization.ToTransportQualifiedQueueName(settings.AuditLogQueue);
53+
5254
auditPersister = new AuditPersister(unitOfWorkFactory, enrichers, ingestedAuditMeter, ingestedSagaAuditMeter, auditBulkInsertDurationMeter, sagaAuditBulkInsertDurationMeter, bulkInsertCommitDurationMeter, messageSession, messageDispatcher);
5355
}
5456

5557
public async Task Ingest(List<MessageContext> contexts)
5658
{
57-
if (log.IsDebugEnabled)
59+
if (Log.IsDebugEnabled)
5860
{
59-
log.Debug($"Ingesting {contexts.Count} message contexts");
61+
Log.Debug($"Ingesting {contexts.Count} message contexts");
6062
}
6163

6264
var stored = await auditPersister.Persist(contexts);
@@ -65,14 +67,14 @@ public async Task Ingest(List<MessageContext> contexts)
6567
{
6668
if (settings.ForwardAuditMessages)
6769
{
68-
if (log.IsDebugEnabled)
70+
if (Log.IsDebugEnabled)
6971
{
70-
log.Debug($"Forwarding {stored.Count} messages");
72+
Log.Debug($"Forwarding {stored.Count} messages");
7173
}
72-
await Forward(stored, settings.AuditLogQueue);
73-
if (log.IsDebugEnabled)
74+
await Forward(stored, logQueueAddress);
75+
if (Log.IsDebugEnabled)
7476
{
75-
log.Debug("Forwarded messages");
77+
Log.Debug("Forwarded messages");
7678
}
7779
}
7880

@@ -83,9 +85,9 @@ public async Task Ingest(List<MessageContext> contexts)
8385
}
8486
catch (Exception e)
8587
{
86-
if (log.IsWarnEnabled)
88+
if (Log.IsWarnEnabled)
8789
{
88-
log.Warn("Forwarding messages failed", e);
90+
Log.Warn("Forwarding messages failed", e);
8991
}
9092

9193
// making sure to rethrow so that all messages get marked as failed
@@ -140,7 +142,7 @@ public async Task VerifyCanReachForwardingAddress()
140142
new TransportOperation(
141143
new OutgoingMessage(Guid.Empty.ToString("N"),
142144
[], Array.Empty<byte>()),
143-
new UnicastAddressTag(settings.AuditLogQueue)
145+
new UnicastAddressTag(logQueueAddress)
144146
)
145147
);
146148

@@ -155,7 +157,9 @@ public async Task VerifyCanReachForwardingAddress()
155157
readonly AuditPersister auditPersister;
156158
readonly Settings settings;
157159
readonly Lazy<IMessageDispatcher> messageDispatcher;
160+
readonly string logQueueAddress;
158161

159-
static readonly ILog log = LogManager.GetLogger<AuditIngestor>();
162+
static readonly long FrequencyInMilliseconds = Stopwatch.Frequency / 1000;
163+
static readonly ILog Log = LogManager.GetLogger<AuditIngestor>();
160164
}
161165
}

src/ServiceControl.Audit/Infrastructure/NServiceBusFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static void Configure(Settings.Settings settings, ITransportCustomization
4444
routing.RouteToEndpoint(typeof(RegisterNewEndpoint), serviceControlLogicalQueue);
4545
routing.RouteToEndpoint(typeof(MarkMessageFailureResolvedByRetry), serviceControlLogicalQueue);
4646

47-
configuration.ReportCustomChecksTo(settings.ServiceControlQueueAddress);
47+
configuration.ReportCustomChecksTo(transportCustomization.ToTransportQualifiedQueueName(settings.ServiceControlQueueAddress));
4848
}
4949

5050
configuration.GetSettings().Set(settings.LoggingSettings);

0 commit comments

Comments
 (0)