Closed EtherZa closed 3 months ago
@EtherZa looks good to me. Let me know once you've done with the changes and resolved the comments.
I've re-run the tests, there seems to be some transient connection to Azure SQL.
I believe there is a clash between the two Outbox tests and PRs that apply different sets of migrations. Perhaps the delete from the migrations table does not serve well.
I dropped the two tables from the Azure SQL instance to let them be recreated and migration table re-populated.
DROP TABLE [dbo].[__EFMigrationsHistory]
DROP TABLE [dbo].[IntTest_Customer]
The last error from the integration tests:
[xUnit.net 00:01:38.65] [17:50:44 ERR] Microsoft.EntityFrameworkCore.Database.Command Failed executing DbCommand (161ms) [Parameters=[], CommandType='"Text"', CommandTimeout='30']
[xUnit.net 00:01:38.65] ALTER TABLE [IntTest_Customer] ADD [UniqueId] nvarchar(max) NULL;
Failed SlimMessageBus.Host.Outbox.DbContext.Test.OutboxTests.Given_CommandHandlerInTransaction_When_ExceptionThrownDuringHandlingRaisedAtTheEnd_Then_TransactionIsRolledBack_And_NoDataSaved_And_NoEventRaised(transactionType: SqlTransaction, busType: AzureSB, messageCount: 100) [17 s]
Error Message:
Microsoft.Data.SqlClient.SqlException : Column names in each table must be unique. Column name 'UniqueId' in table 'IntTest_Customer' is specified more than once.
@zarusz One other enhancement that you may want to consider is to use a unique topic name with AutoDeleteOnIdle
for each test execution to ensure that no messages remain in the subscription from a previous failed test run.
ie. something like
mbb.AddChildBus("ExternalBus", mbb =>
{
var topic = $"tests.outbox-benchmark/customer-events/{Guid.NewGuid():N}";
mbb
.WithProviderServiceBus(cfg =>
{
cfg.ConnectionString = Secrets.Service.PopulateSecrets(configuration["Azure:ServiceBus"]);
cfg.PrefetchCount = 100; // fetch 100 messages at a time
cfg.TopologyProvisioning.CreateTopicOptions = opt => opt.AutoDeleteOnIdle = TimeSpan.FromMinutes(5);
})
I did not make the change now as it will require manually deleting the existing topic before it can be used as a root for this pattern.
Issues
1 New issue
0 Accepted issues
Measures
0 Security Hotspots
91.4% Coverage on New Code
0.0% Duplication on New Code
This is the best I can come up with for a single db implementation.
Use the same schema for both EF and outbox migrations; dropping it on every test. Any test that uses the same db context/schema will need to run in series unfortunately.
On the upside, it will create a completely clean copy of the db for every test run, as well as clean instance of the service bus (with a 5 min auto delete). Repeatable and isolated from other tests while using a single SQL database instance.
If you would like to go the full concurrency/parallel execution route, it might be worth looking at test containers. ASB/AEH can use different topics to achieve the same thing without containers being available.
@EtherZa Well done with the changes - it looks better & clean!
@zarusz I picked up a few issues when running the benchmarks, so threw together a couple fixes
OutboxSendingTask.OnBusLifecycle()
can return a null value - exception thrown inMessageBusBase.OnBusLifecycle()
OutboxBenchmarkTests.SetupServices()
-mbb.AutoStartConsumersEnabled(false);
only propagates if is set before adding a child bus. Child bus was immediately active causing some messages to be consumed before the consumption timer was started.BaseIntegrationTest.EnsureConsumersStarted()
just watched for a consumer to start, but didn't start one.OutboxSendingTask
so thatSendMessage()
can be called directly (internal
modifier). Publishing time can now be isolated from consumption time. Same logic, but shifted the primary loop fromRun()
toSendMessages()
.I have picked up a few logical errors in #260 which is the reason for the delay.