Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PostreSQL Transport #1296

Merged
merged 116 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
a246146
postgre sql transport project
tmasternak Jan 22, 2024
09b4d0d
something that compiles
tmasternak Jan 22, 2024
39a6378
moving from sql types do db types
tmasternak Jan 22, 2024
22c3da3
send infra config
tmasternak Jan 23, 2024
934e2ab
subscribtion config
tmasternak Jan 23, 2024
65a3171
introducing base sql constants class
tmasternak Jan 25, 2024
2dfc369
Introduced PostgreSql Transport Tests Project
poornimanayar Jan 30, 2024
96c3373
Progressing on getting tests to pass for PostgreSql Transport
poornimanayar Jan 31, 2024
dbf603f
Made everything compile and ready for creating Sql statements and run…
dvdstelt Feb 1, 2024
f6876ce
sql to create a queue
dvdstelt Feb 1, 2024
e73516f
Removed different QueueAddressTranslators and interface
dvdstelt Feb 1, 2024
f54e9f0
First test is greeeeeeen!
SzymonPobiega Feb 2, 2024
1a89208
Most tests working
SzymonPobiega Feb 5, 2024
3fa2cc7
SQL for Move Due Delayed Message Text
poornimanayar Feb 7, 2024
6d2d8b2
StoreDelayedMessageText query in place
poornimanayar Feb 8, 2024
6f74820
test are green again
tmasternak Feb 8, 2024
167aeec
sql server and postresql specific send queries
tmasternak Feb 8, 2024
0bb9871
Add a transport test for PostgreSQL delayed delivery
SzymonPobiega Feb 9, 2024
59afe62
Adjust the delay test
SzymonPobiega Feb 9, 2024
3a908b0
Fixed test and added exponential back-off for delayed messages.
dvdstelt Feb 16, 2024
ed55515
Cleanup
dvdstelt Feb 16, 2024
5a40e4a
fixing sql server transport tests
tmasternak Feb 20, 2024
104bdf3
making sql server unit tests work
tmasternak Feb 20, 2024
ec389c4
first step in extracting the the abstraction
tmasternak Feb 21, 2024
cd8b0f7
refactoring dbconnectionfactory
tmasternak Feb 22, 2024
e16f901
Extracted backoffstrategy
dvdstelt Feb 23, 2024
f6bf6b4
Tests for exponential backoff strategy
dvdstelt Feb 23, 2024
3840893
Forgot to add a few files on last commit
dvdstelt Feb 23, 2024
d63fb32
Improved flaky tests and cleaned up some code
dvdstelt Feb 23, 2024
8ed03ac
Fix pub sub
SzymonPobiega Feb 29, 2024
6705b3a
first step in extracting the shared code
tmasternak Feb 29, 2024
c5f3727
expired message purger move
tmasternak Feb 29, 2024
f1f756f
move types moved
tmasternak Feb 29, 2024
23c9093
TransportReceiver successfully migrated
SzymonPobiega Mar 1, 2024
c4f1d9a
moving queue creator
tmasternak Mar 4, 2024
010bef9
Deal with the addressing
SzymonPobiega Mar 7, 2024
93d7e5a
Finish refactoring the addressing
SzymonPobiega Mar 8, 2024
19d8def
fixing tests
tmasternak Mar 8, 2024
1b1166b
Modified ReceiveText which hopefully fixes bug
dvdstelt Mar 14, 2024
8233283
Add acceptance tests
SzymonPobiega Mar 18, 2024
5eae8a3
Fix the cleanup
SzymonPobiega Mar 18, 2024
1e77205
handle concurrent queue creation for postgreSQL
tmasternak Mar 20, 2024
3586992
Working on PostgreSQL identifier limits
poornimanayar Mar 21, 2024
91b16d9
Finished PostgreSQL identifier limits
dvdstelt Mar 22, 2024
2199ebb
Fixed issue around identifier lengths in TransportTests
dvdstelt Mar 22, 2024
3296c8c
Made the test name generation consistent between acceptance and trans…
SzymonPobiega Mar 26, 2024
9be8359
Use deterministic hash that does not change between test runs
SzymonPobiega Mar 26, 2024
59806c1
handling auto-created sequence name trunctaion
tmasternak Mar 27, 2024
6ffc6a1
capturing concurrent subscription table creation
tmasternak Mar 28, 2024
c7d061a
cleaning up tables and sequences in tests
tmasternak Mar 28, 2024
570fa8b
test override to handle extended queue names due to instance discrim…
tmasternak Mar 28, 2024
1cb084d
shared key names for passing transport transaction
tmasternak Apr 3, 2024
60c7e14
first step in bringing schema acceptance tests
tmasternak Apr 3, 2024
080143a
Approved API changes
SzymonPobiega Apr 4, 2024
8434529
Fixes to address and schema handling
SzymonPobiega Apr 4, 2024
9ca7ec4
Fixes to multi-schema tests
SzymonPobiega Apr 5, 2024
d0220ca
native delayed delivery
tmasternak Apr 5, 2024
ef84754
Fix the code that moves delayed messages to the poison queue if their…
SzymonPobiega Apr 8, 2024
0f6963d
more tests
tmasternak Apr 9, 2024
ea8f9de
Remove unused line
dvdstelt Apr 10, 2024
25b896e
Trying to get connectionfactory to work
dvdstelt Apr 10, 2024
3bb960f
fixing transport constructors
tmasternak Apr 16, 2024
8f69a16
bodystring column support
tmasternak Apr 23, 2024
e75bd7a
test fixes
tmasternak Apr 23, 2024
89c4f86
Improvements to the transaction handling process
SzymonPobiega Apr 25, 2024
1df10ae
refactoring transport transaction
tmasternak Apr 25, 2024
f3b11b2
add user provided transactions as extension method
tmasternak Apr 25, 2024
c6cdf91
remove unused test-related extension point
tmasternak May 2, 2024
26278d0
postgre sql public api - initial step
tmasternak May 2, 2024
548231e
fixing postgre schema test
tmasternak May 3, 2024
326a7e2
postgresql approvals
tmasternak May 3, 2024
d40e9a6
test fixes
tmasternak May 3, 2024
0330aff
postgre legacy api tests
tmasternak May 6, 2024
379ef9a
static postgre name helper
tmasternak May 6, 2024
89ffc13
sql server static name helper
tmasternak May 6, 2024
a04d76a
streaming support tweaks
tmasternak May 6, 2024
d1dfbf2
startup diagnostics
tmasternak May 6, 2024
0685716
removing unused code
tmasternak May 6, 2024
2a5f893
bring back memory leak fix from #1279
tmasternak May 7, 2024
865a012
removing Guard class in postgre
tmasternak May 7, 2024
63c33c7
removing old sql client usings
tmasternak May 7, 2024
09c6da4
targeting rtm of core in postgresql
tmasternak May 7, 2024
cfac7b0
bringing back #1277
tmasternak May 7, 2024
f07ed6a
package updates
tmasternak May 7, 2024
75570a0
bring back #1289
tmasternak May 7, 2024
5c8082f
update sdk refs
tmasternak May 7, 2024
7a8e683
updating approvals
tmasternak May 7, 2024
820ebd6
temporarily ignore sql server tests
tmasternak May 7, 2024
8bd27b8
setup postgre tests
tmasternak May 7, 2024
626a2bf
postgre tests stage 2
tmasternak May 7, 2024
744c970
postgre container with prepared txs
tmasternak May 7, 2024
0e70ee7
Update ci.yml
tmasternak May 7, 2024
65bac33
Update ci.yml
tmasternak May 7, 2024
f220a63
Update ci.yml
tmasternak May 7, 2024
fd3729a
create scheams for postgre and increaste prepared transactions limit
tmasternak May 7, 2024
2dec537
quoting created schema
tmasternak May 7, 2024
daafb9b
re-enable sql server tests
tmasternak May 8, 2024
722aece
disable dtc test for postgre on linux
tmasternak May 8, 2024
1842af0
fixing build
tmasternak May 8, 2024
77e6173
classifying postgre deadlock excpetion
tmasternak May 8, 2024
65c62d3
removing dep on uuid-ossp extension
tmasternak May 8, 2024
318c105
removing transaction scope support from postrgresql
tmasternak May 8, 2024
4c2c220
all dispatch operations outside of handler in a single transaction
tmasternak May 8, 2024
80c5c93
fix
tmasternak May 8, 2024
188ba1a
turning off transactionscope tests when tx mode is configured manually
tmasternak May 9, 2024
5aa67f7
Make progress on TODO list
SzymonPobiega May 9, 2024
5678963
Fix the build
SzymonPobiega May 9, 2024
6b29c2c
Fix failed test
SzymonPobiega May 9, 2024
31d902b
Fix easy TODOs
SzymonPobiega May 10, 2024
bd51099
Upgrade to latest npgsql
SzymonPobiega May 10, 2024
2924a01
Approve API changes
SzymonPobiega May 10, 2024
ef2f114
sequence cleanup is not nedded
tmasternak May 10, 2024
f6d84f3
more todos
tmasternak May 10, 2024
530b72a
removing legacy sql callback headers support
tmasternak May 10, 2024
63c2ac0
fixing/removing todos
tmasternak May 13, 2024
9b1e358
fixing the last todo
tmasternak May 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,65 @@ jobs:
sqlcmd -Q "CREATE SCHEMA receiver AUTHORIZATION db_owner" -d "nservicebus"
sqlcmd -Q "CREATE SCHEMA sender AUTHORIZATION db_owner" -d "nservicebus"
sqlcmd -Q "CREATE SCHEMA db@ AUTHORIZATION db_owner" -d "nservicebus"
- name: Azure login
uses: azure/login@v2.1.0
with:
creds: ${{ secrets.AZURE_ACI_CREDENTIALS }}
- name: Setup PostgreSql 15.x
id: setup-postgresql
run: |
echo "Getting the Azure region in which this workflow is running..."
$hostInfo = curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertFrom-Json
$region = $hostInfo.compute.location
echo "Actions agent running in Azure region: $region"

$name = "postgres-$(Get-Random)"
$packageTag = "Package=SqlPersistence"
$runnerOsTag = "RunnerOS=$($Env:RUNNER_OS)"
$dateTag = "Created=$(Get-Date -Format "yyyy-MM-dd")"

$password = [guid]::NewGuid().ToString("n")
echo "::add-mask::$password"

echo "Creating PostgreSQL container $name (This can take a while)"
$details = az container create --image postgres:15 --name $name --location $region --dns-name-label $name --resource-group GitHubActions-RG --cpu 2 --memory 8 --ports 5432 --ip-address public --environment-variables POSTGRES_PASSWORD="$password" --command-line "docker-entrypoint.sh postgres --max-prepared-transactions=10" | ConvertFrom-Json
echo "name=$name" | Out-File -FilePath $Env:GITHUB_OUTPUT -Encoding utf-8 -Append

echo "Tagging container"
$ignore = az tag create --resource-id $details.id --tags $packageTag $runnerOsTag $dateTag

$fqdn = $details.ipAddress.fqdn
echo "::add-mask::$fqdn"

$connectionString = "User ID=postgres;Password=$password;Host=$fqdn;Port=5432;Database=postgres;"
echo "PostgreSqlTransportConnectionString=$connectionString" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append

$env:PGPASSWORD = $password

# psql not in PATH on Windows
if ($Env:RUNNER_OS -eq 'Windows') {
$Env:PATH = $Env:PATH + ';' + $Env:PGBIN
}

for ($i = 0; $i -lt 24; $i++) { ## 2 minute timeout
echo "Checking for PostgreSQL connectivity $($i+1)/30..."
$ignore = psql --host $fqdn --username=postgres --list
if ($?) {
echo "Connection successful"
break;
}
sleep 5
}

# create schemas
$ignore = psql --host $fqdn --username=postgres --dbname=postgres --command 'CREATE SCHEMA IF NOT EXISTS sender'
$ignore = psql --host $fqdn --username=postgres --dbname=postgres --command 'CREATE SCHEMA IF NOT EXISTS receiver'
$ignore = psql --host $fqdn --username=postgres --dbname=postgres --command 'CREATE SCHEMA IF NOT EXISTS "db@"'
- name: Run tests
uses: Particular/run-tests-action@v1.7.0
- name: Teardown infrastructure
if: ${{ always() }}
run: |
echo "Removing container ${{ steps.setup-postgresql.outputs.name }}"
$ignore = az container delete --resource-group GitHubActions-RG --name ${{ steps.setup-postgresql.outputs.name }} --yes
echo "Removal complete"
30 changes: 30 additions & 0 deletions src/NServiceBus.SqlServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Transport.SqlSe
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Transport.SqlServer.UnitTests", "NServiceBus.Transport.SqlServer.UnitTests\NServiceBus.Transport.SqlServer.UnitTests.csproj", "{F08C8BAB-C329-4F96-A6AF-F25419C623FD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Transport.PostgreSql", "NServiceBus.Transport.PostgreSql\NServiceBus.Transport.PostgreSql.csproj", "{926EFB58-F51F-4BF8-9625-A11F53950FA4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Transport.PostgreSql.TransportTests", "NServiceBus.Transport.PostgreSql.TransportTests\NServiceBus.Transport.PostgreSql.TransportTests.csproj", "{76B19C3B-7AB6-4BB7-AF39-03F76701521F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.Transport.Sql.Shared", "NServiceBus.Transport.Sql.Shared\NServiceBus.Transport.Sql.Shared.csproj", "{8028DDF3-7565-49B8-B71C-F321A1755C51}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Transport.PostgreSql.AcceptanceTests", "NServiceBus.Transport.PostgreSql.AcceptanceTests\NServiceBus.Transport.PostgreSql.AcceptanceTests.csproj", "{F0B7EDA3-AB83-4FE7-986F-EE2D17484B52}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Transport.PostgreSql.UnitTests", "NServiceBus.Transport.PostgreSql.UnitTests\NServiceBus.Transport.PostgreSql.UnitTests.csproj", "{738DD684-77B8-4A6E-AE73-ED98023E5957}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -48,6 +58,26 @@ Global
{F08C8BAB-C329-4F96-A6AF-F25419C623FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F08C8BAB-C329-4F96-A6AF-F25419C623FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F08C8BAB-C329-4F96-A6AF-F25419C623FD}.Release|Any CPU.Build.0 = Release|Any CPU
{926EFB58-F51F-4BF8-9625-A11F53950FA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{926EFB58-F51F-4BF8-9625-A11F53950FA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{926EFB58-F51F-4BF8-9625-A11F53950FA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{926EFB58-F51F-4BF8-9625-A11F53950FA4}.Release|Any CPU.Build.0 = Release|Any CPU
{76B19C3B-7AB6-4BB7-AF39-03F76701521F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76B19C3B-7AB6-4BB7-AF39-03F76701521F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76B19C3B-7AB6-4BB7-AF39-03F76701521F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76B19C3B-7AB6-4BB7-AF39-03F76701521F}.Release|Any CPU.Build.0 = Release|Any CPU
{8028DDF3-7565-49B8-B71C-F321A1755C51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8028DDF3-7565-49B8-B71C-F321A1755C51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8028DDF3-7565-49B8-B71C-F321A1755C51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8028DDF3-7565-49B8-B71C-F321A1755C51}.Release|Any CPU.Build.0 = Release|Any CPU
{F0B7EDA3-AB83-4FE7-986F-EE2D17484B52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0B7EDA3-AB83-4FE7-986F-EE2D17484B52}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0B7EDA3-AB83-4FE7-986F-EE2D17484B52}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0B7EDA3-AB83-4FE7-986F-EE2D17484B52}.Release|Any CPU.Build.0 = Release|Any CPU
{738DD684-77B8-4A6E-AE73-ED98023E5957}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{738DD684-77B8-4A6E-AE73-ED98023E5957}.Debug|Any CPU.Build.0 = Debug|Any CPU
{738DD684-77B8-4A6E-AE73-ED98023E5957}.Release|Any CPU.ActiveCfg = Release|Any CPU
{738DD684-77B8-4A6E-AE73-ED98023E5957}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
10 changes: 10 additions & 0 deletions src/NServiceBus.Transport.PostgreSql.AcceptanceTests/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[*.cs]

# Justification: Test project
dotnet_diagnostic.CA2007.severity = none

# may be enabled in future
dotnet_diagnostic.PS0018.severity = none # A task-returning method should have a CancellationToken parameter unless it has a parameter implementing ICancellableContext

# Justification: Tests don't support cancellation and don't need to forward IMessageHandlerContext.CancellationToken
dotnet_diagnostic.NSB0002.severity = suggestion
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using NServiceBus;
using NServiceBus.Configuration.AdvancedExtensibility;
using NServiceBus.Transport;
using NServiceBus.Transport.PostgreSql;

static class ConfigurationHelpers
{
public static PostgreSqlTransport ConfigureSqlServerTransport(this EndpointConfiguration configuration)
{
return (PostgreSqlTransport)configuration.GetSettings().Get<TransportDefinition>();
}

public static string BuildAddressWithSchema(string endpointName, string schema)
{
return $"{schema}.{endpointName}";
}

public static string QuoteSchema(string schema)
{
return $"\"{schema}\"";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Npgsql;
using NServiceBus;
using NServiceBus.AcceptanceTesting.Support;
using NServiceBus.Transport.PostgreSql;
using NServiceBus.Transport.SqlServer;

public class ConfigureEndpointPostgreSqlTransport : IConfigureEndpointTestExecution
{
public ConfigureEndpointPostgreSqlTransport(PostgreSqlTransport transport)
{
this.transport = transport;
}

public ConfigureEndpointPostgreSqlTransport()
{
connectionString = Environment.GetEnvironmentVariable("PostgreSqlTransportConnectionString") ?? @"User ID=user;Password=admin;Host=localhost;Port=54320;Database=nservicebus;Pooling=true;Connection Lifetime=0;Include Error Detail=true";

transport = new PostgreSqlTransport(connectionString);
transport.Subscriptions.DisableCaching = true;

//On non windows operating systems we need to explicitly set the transaction mode to SendsAtomicWithReceive since distributed transactions is not available there
if (!OperatingSystem.IsWindows() && transport.TransportTransactionMode == TransportTransactionMode.TransactionScope)
{
transport.TransportTransactionMode = TransportTransactionMode.SendsAtomicWithReceive;
}
}

public Task Configure(string endpointName, EndpointConfiguration configuration, RunSettings runSettings, PublisherMetadata publisherMetadata)
{
doNotCleanNativeSubscriptions = runSettings.TryGet<bool>("DoNotCleanNativeSubscriptions", out _);

configuration.UseTransport(transport);
this.endpointName = endpointName;

return Task.FromResult(0);
}

public async Task Cleanup()
{
Func<Task<NpgsqlConnection>> factory = async () =>
{
if (transport.ConnectionString != null)
{
var connection = new NpgsqlConnection(transport.ConnectionString);
await connection.OpenAsync().ConfigureAwait(false);
return connection;
}

return await transport.ConnectionFactory(CancellationToken.None).ConfigureAwait(false);
};

using (var conn = await factory().ConfigureAwait(false))
{
var queueAddresses = transport.Testing.ReceiveAddresses;
var delayedQueueAddress = transport.Testing.DelayedDeliveryQueue;
var defaultSchema = transport.DefaultSchema;

var commandTextBuilder = new StringBuilder();

//No clean-up for send-only endpoints
if (queueAddresses != null)
{
foreach (var address in queueAddresses)
{
commandTextBuilder.AppendLine($"DROP TABLE IF EXISTS {address};");
}
}

//Null-check because if an exception is thrown before startup these fields might be empty
if (delayedQueueAddress != null)
{
commandTextBuilder.AppendLine($"DROP TABLE IF EXISTS {delayedQueueAddress};");
}

var subscriptionTableName = transport.Testing.SubscriptionTable;

if (!doNotCleanNativeSubscriptions && !string.IsNullOrEmpty(subscriptionTableName))
{
commandTextBuilder.AppendLine($"DROP TABLE IF EXISTS {subscriptionTableName};");
}

var commandText = commandTextBuilder.ToString();
if (!string.IsNullOrEmpty(commandText))
{
await TryDeleteTables(conn, commandText);
}
}
}

async Task TryDeleteTables(NpgsqlConnection conn, string commandText)
{
try
{
using (var comm = conn.CreateCommand())
{
comm.CommandText = commandText;
await comm.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}
catch (Exception e)
{
if (!e.Message.Contains("it does not exist or you do not have permission"))
{
throw new Exception($"Failed to execute query in {endpointName}: {commandText}", e);
}
}
}

bool doNotCleanNativeSubscriptions;
PostgreSqlTransport transport;
string connectionString;
string endpointName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace NServiceBus.Transport.PostgreSql.AcceptanceTests
{
using NServiceBus.AcceptanceTests.EndpointTemplates;
using PostgreSql;

public class CustomizedServer : DefaultServer
{
public CustomizedServer(PostgreSqlTransport transport)
{
TransportConfiguration = new ConfigureEndpointPostgreSqlTransport(transport);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace NServiceBus.Transport.SqlServer.AcceptanceTests.MultiSchema
{
using System;
using System.Threading.Tasks;
using AcceptanceTesting;
using NServiceBus.AcceptanceTests;
using NServiceBus.AcceptanceTests.EndpointTemplates;
using NUnit.Framework;

public class When_custom_schema_configured_for_error_queue : NServiceBusAcceptanceTest
{
[Test]
public async Task Error_should_be_sent_to_table_in_configured_schema()
{
var ctx = await Scenario.Define<Context>()
.WithEndpoint<Sender>(b =>
{
b.DoNotFailOnErrorMessages();
b.When((bus, c) => bus.SendLocal(new Message()));
})
.WithEndpoint<ErrorSpy>()
.Done(c => c.FailedMessageProcessed)
.Run();

Assert.True(ctx.FailedMessageProcessed, "Message should be moved to error queue in custom schema");
}

public class Context : ScenarioContext
{
public bool FailedMessageProcessed { get; set; }
}

public class Sender : EndpointConfigurationBuilder
{
public Sender()
{
EndpointSetup<DefaultServer>(c =>
{
var errorSpyName = AcceptanceTesting.Customization.Conventions.EndpointNamingConvention(typeof(ErrorSpy));

c.SendFailedMessagesTo(errorSpyName);

c.Recoverability()
.Immediate(i => i.NumberOfRetries(0))
.Delayed(d => d.NumberOfRetries(0));

var transport = c.ConfigureSqlServerTransport();
transport.Schema.UseSchemaForQueue(errorSpyName, ErrorSpySchema);
});
}

class Handler : IHandleMessages<Message>
{
public Task Handle(Message message, IMessageHandlerContext context)
{
throw new Exception("Simulated exception");
}
}
}

public class ErrorSpy : EndpointConfigurationBuilder
{
public ErrorSpy()
{
EndpointSetup<DefaultServer>(c =>
{
c.ConfigureSqlServerTransport().DefaultSchema = ErrorSpySchema;
});
}

class Handler : IHandleMessages<Message>
{
readonly Context scenarioContext;
public Handler(Context scenarioContext)
{
this.scenarioContext = scenarioContext;
}

public Task Handle(Message message, IMessageHandlerContext context)
{
scenarioContext.FailedMessageProcessed = true;

return Task.FromResult(0);
}
}
}

public class Message : ICommand { }

const string ErrorSpySchema = "receiver";
}
}