Skip to content

Commit 1baba0a

Browse files
Add new configuration API for Transactional Session v3.3.0 (#757)
* Add new api * Approve * Add test * Fix capture logic * Remove uneeded behavior * Test new way of capturing the service provider (#758) * Test new way of capturing the service provider * Cleanup * Fix null ref * Fix reflection * Better exception * Cleanup * Primary ctor * updae to beta.2 * Use beta 3 * Use 3.3.0 of tx session --------- Co-authored-by: Christian <christian.quiros+github@gmail.com>
1 parent 6c29419 commit 1baba0a

File tree

10 files changed

+195
-70
lines changed

10 files changed

+195
-70
lines changed

src/NServiceBus.Storage.MongoDB.TransactionalSession.AcceptanceTests/Infrastructure/CaptureServiceProviderStartupTask.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@
33
using System;
44
using System.Threading;
55
using System.Threading.Tasks;
6-
using NServiceBus.AcceptanceTesting;
7-
using NServiceBus.Features;
6+
using Features;
87

98
public class CaptureServiceProviderStartupTask : FeatureStartupTask
109
{
11-
public CaptureServiceProviderStartupTask(IServiceProvider serviceProvider, ScenarioContext context)
12-
{
13-
if (context is IInjectServiceProvider c)
14-
{
15-
c.ServiceProvider = serviceProvider;
16-
}
17-
}
10+
public CaptureServiceProviderStartupTask(IServiceProvider serviceProvider, TransactionalSessionTestContext context, string endpointName) => context.RegisterServiceProvider(serviceProvider, endpointName);
1811

1912
protected override Task OnStart(IMessageSession session, CancellationToken cancellationToken = default) => Task.CompletedTask;
2013

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
namespace NServiceBus.TransactionalSession.AcceptanceTests;
2+
3+
using System;
4+
using System.IO;
5+
using System.Threading.Tasks;
6+
using AcceptanceTesting;
7+
using AcceptanceTesting.Customization;
8+
using AcceptanceTesting.Support;
9+
using Configuration.AdvancedExtensibility;
10+
using NUnit.Framework;
11+
12+
public class DefaultServer : IEndpointSetupTemplate
13+
{
14+
public virtual async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizations,
15+
Func<EndpointConfiguration, Task> configurationBuilderCustomization)
16+
{
17+
var endpointConfiguration = new EndpointConfiguration(endpointCustomizations.EndpointName);
18+
19+
endpointConfiguration.EnableInstallers();
20+
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
21+
endpointConfiguration.Recoverability()
22+
.Delayed(delayed => delayed.NumberOfRetries(0))
23+
.Immediate(immediate => immediate.NumberOfRetries(0));
24+
endpointConfiguration.SendFailedMessagesTo("error");
25+
26+
var storageDir = Path.Combine(Path.GetTempPath(), "learn", TestContext.CurrentContext.Test.ID);
27+
28+
endpointConfiguration.UseTransport(new AcceptanceTestingTransport { StorageLocation = storageDir });
29+
30+
var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
31+
persistence.EnableTransactionalSession();
32+
persistence.MongoClient(SetupFixture.MongoClient);
33+
persistence.DatabaseName(SetupFixture.DatabaseName);
34+
persistence.UseTransactions(true);
35+
36+
endpointConfiguration.GetSettings().Set(persistence);
37+
38+
if (runDescriptor.ScenarioContext is TransactionalSessionTestContext testContext)
39+
{
40+
endpointConfiguration.RegisterStartupTask(sp => new CaptureServiceProviderStartupTask(sp, testContext, endpointCustomizations.EndpointName));
41+
}
42+
43+
await configurationBuilderCustomization(endpointConfiguration).ConfigureAwait(false);
44+
45+
// scan types at the end so that all types used by the configuration have been loaded into the AppDomain
46+
endpointConfiguration.TypesToIncludeInScan(endpointCustomizations.GetTypesScopedByTestClass());
47+
48+
return endpointConfiguration;
49+
}
50+
}

src/NServiceBus.Storage.MongoDB.TransactionalSession.AcceptanceTests/Infrastructure/IInjectServiceProvider.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/NServiceBus.Storage.MongoDB.TransactionalSession.AcceptanceTests/Infrastructure/TransactionSessionDefaultServer.cs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,18 @@
11
namespace NServiceBus.TransactionalSession.AcceptanceTests
22
{
33
using System;
4-
using System.IO;
54
using System.Threading.Tasks;
6-
using NServiceBus.AcceptanceTesting;
7-
using NServiceBus.AcceptanceTesting.Customization;
8-
using NServiceBus.AcceptanceTesting.Support;
9-
using NUnit.Framework;
5+
using AcceptanceTesting.Support;
6+
using Configuration.AdvancedExtensibility;
107

11-
public class TransactionSessionDefaultServer : IEndpointSetupTemplate
8+
public class TransactionSessionDefaultServer : DefaultServer
129
{
13-
public virtual async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizations,
14-
Func<EndpointConfiguration, Task> configurationBuilderCustomization)
10+
public override async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomization, Func<EndpointConfiguration, Task> configurationBuilderCustomization)
1511
{
16-
var endpointConfiguration = new EndpointConfiguration(endpointCustomizations.EndpointName);
12+
var endpointConfiguration = await base.GetConfiguration(runDescriptor, endpointCustomization, configurationBuilderCustomization);
1713

18-
endpointConfiguration.EnableInstallers();
19-
endpointConfiguration.UseSerialization<SystemJsonSerializer>();
20-
endpointConfiguration.Recoverability()
21-
.Delayed(delayed => delayed.NumberOfRetries(0))
22-
.Immediate(immediate => immediate.NumberOfRetries(0));
23-
endpointConfiguration.SendFailedMessagesTo("error");
24-
25-
var storageDir = Path.Combine(Path.GetTempPath(), "learn", TestContext.CurrentContext.Test.ID);
26-
27-
endpointConfiguration.UseTransport(new AcceptanceTestingTransport
28-
{
29-
StorageLocation = storageDir
30-
});
31-
32-
var mongoSettings = endpointConfiguration.UsePersistence<MongoPersistence>();
33-
mongoSettings.EnableTransactionalSession();
34-
mongoSettings.MongoClient(SetupFixture.MongoClient);
35-
mongoSettings.DatabaseName(SetupFixture.DatabaseName);
36-
mongoSettings.UseTransactions(true);
37-
38-
endpointConfiguration.RegisterStartupTask(sp => new CaptureServiceProviderStartupTask(sp, runDescriptor.ScenarioContext));
39-
40-
await configurationBuilderCustomization(endpointConfiguration).ConfigureAwait(false);
41-
42-
// scan types at the end so that all types used by the configuration have been loaded into the AppDomain
43-
endpointConfiguration.TypesToIncludeInScan(endpointCustomizations.GetTypesScopedByTestClass());
14+
endpointConfiguration.GetSettings().Get<PersistenceExtensions<MongoPersistence>>()
15+
.EnableTransactionalSession();
4416

4517
return endpointConfiguration;
4618
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace NServiceBus.TransactionalSession.AcceptanceTests;
2+
3+
using System;
4+
using System.Collections.Concurrent;
5+
using System.Reflection;
6+
using AcceptanceTesting;
7+
8+
public class TransactionalSessionTestContext : ScenarioContext
9+
{
10+
public IServiceProvider ServiceProvider
11+
{
12+
get
13+
{
14+
var property = typeof(ScenarioContext).GetProperty("CurrentEndpoint", BindingFlags.NonPublic | BindingFlags.Static);
15+
16+
if (property!.GetValue(this) is not string endpointName)
17+
{
18+
throw new InvalidOperationException("Access to the service provider of the endpoint is only possible with in a When statement.");
19+
}
20+
21+
if (!serviceProviders.TryGetValue(endpointName, out var serviceProvider))
22+
{
23+
throw new InvalidOperationException("Could not find service provider for endpoint " + endpointName);
24+
}
25+
26+
return serviceProvider;
27+
}
28+
}
29+
30+
public void RegisterServiceProvider(IServiceProvider serviceProvider, string endpointName) => serviceProviders[endpointName] = serviceProvider;
31+
32+
readonly ConcurrentDictionary<string, IServiceProvider> serviceProviders = new();
33+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
namespace NServiceBus.TransactionalSession.AcceptanceTests;
2+
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using AcceptanceTesting;
7+
using AcceptanceTesting.Customization;
8+
using Configuration.AdvancedExtensibility;
9+
using NUnit.Framework;
10+
11+
public class When_using_outbox_send_only : NServiceBusAcceptanceTest
12+
{
13+
[Test()]
14+
public async Task Should_send_messages_on_transactional_session_commit()
15+
{
16+
var context = await Scenario.Define<Context>()
17+
.WithEndpoint<SendOnlyEndpoint>(s => s.When(async (_, ctx) =>
18+
{
19+
using var scope = ctx.ServiceProvider.CreateScope();
20+
using var transactionalSession = scope.ServiceProvider.GetRequiredService<ITransactionalSession>();
21+
await transactionalSession.Open(new MongoOpenSessionOptions());
22+
23+
var options = new SendOptions();
24+
25+
options.SetDestination(Conventions.EndpointNamingConvention.Invoke(typeof(AnotherEndpoint)));
26+
27+
await transactionalSession.Send(new SampleMessage(), options);
28+
29+
await transactionalSession.Commit(CancellationToken.None);
30+
}))
31+
.WithEndpoint<AnotherEndpoint>()
32+
.WithEndpoint<ProcessorEndpoint>()
33+
.Done(c => c.MessageReceived)
34+
.Run();
35+
36+
Assert.That(context.MessageReceived, Is.True);
37+
}
38+
39+
class Context : TransactionalSessionTestContext
40+
{
41+
public bool MessageReceived { get; set; }
42+
}
43+
44+
class SendOnlyEndpoint : EndpointConfigurationBuilder
45+
{
46+
public SendOnlyEndpoint() => EndpointSetup<DefaultServer>(c =>
47+
{
48+
var persistence = c.GetSettings().Get<PersistenceExtensions<MongoPersistence>>();
49+
50+
var options = new TransactionalSessionOptions { ProcessorEndpoint = Conventions.EndpointNamingConvention.Invoke(typeof(ProcessorEndpoint)) };
51+
52+
persistence.EnableTransactionalSession(options);
53+
54+
c.EnableOutbox();
55+
c.SendOnly();
56+
});
57+
}
58+
59+
class AnotherEndpoint : EndpointConfigurationBuilder
60+
{
61+
public AnotherEndpoint() => EndpointSetup<DefaultServer>();
62+
63+
class SampleHandler(Context testContext) : IHandleMessages<SampleMessage>
64+
{
65+
public Task Handle(SampleMessage message, IMessageHandlerContext context)
66+
{
67+
testContext.MessageReceived = true;
68+
69+
return Task.CompletedTask;
70+
}
71+
}
72+
}
73+
74+
class ProcessorEndpoint : EndpointConfigurationBuilder
75+
{
76+
public ProcessorEndpoint() => EndpointSetup<TransactionSessionWithOutboxEndpoint>();
77+
}
78+
79+
class SampleMessage : ICommand
80+
{
81+
}
82+
}

src/NServiceBus.Storage.MongoDB.TransactionalSession.AcceptanceTests/When_using_transactional_session.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
namespace NServiceBus.TransactionalSession.AcceptanceTests
22
{
3-
using System;
4-
using System.Threading;
53
using System.Threading.Tasks;
64
using AcceptanceTesting;
75
using Microsoft.Extensions.DependencyInjection;
@@ -166,12 +164,11 @@ await mongoSession.Client.GetDatabase(SetupFixture.DatabaseName)
166164
Assert.That(documents.ToList().Count, Is.EqualTo(1));
167165
}
168166

169-
class Context : ScenarioContext, IInjectServiceProvider
167+
class Context : TransactionalSessionTestContext
170168
{
171169
public bool MessageReceived { get; set; }
172170
public bool CompleteMessageReceived { get; set; }
173171
public string SessionId { get; set; }
174-
public IServiceProvider ServiceProvider { get; set; }
175172
}
176173

177174
class AnEndpoint : EndpointConfigurationBuilder
@@ -188,32 +185,24 @@ public AnEndpoint()
188185
}
189186
}
190187

191-
class SampleHandler : IHandleMessages<SampleMessage>
188+
class SampleHandler(Context testContext) : IHandleMessages<SampleMessage>
192189
{
193-
public SampleHandler(Context testContext) => this.testContext = testContext;
194-
195190
public Task Handle(SampleMessage message, IMessageHandlerContext context)
196191
{
197192
testContext.MessageReceived = true;
198193

199194
return Task.CompletedTask;
200195
}
201-
202-
readonly Context testContext;
203196
}
204197

205-
class CompleteTestMessageHandler : IHandleMessages<CompleteTestMessage>
198+
class CompleteTestMessageHandler(Context testContext) : IHandleMessages<CompleteTestMessage>
206199
{
207-
public CompleteTestMessageHandler(Context context) => testContext = context;
208-
209200
public Task Handle(CompleteTestMessage message, IMessageHandlerContext context)
210201
{
211202
testContext.CompleteMessageReceived = true;
212203

213204
return Task.CompletedTask;
214205
}
215-
216-
readonly Context testContext;
217206
}
218207
}
219208

src/NServiceBus.Storage.MongoDB.TransactionalSession.Tests/ApprovalFiles/APIApprovals.Approve.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace NServiceBus.TransactionalSession
77
public static class MongoTransactionalSessionExtensions
88
{
99
public static NServiceBus.PersistenceExtensions<NServiceBus.MongoPersistence> EnableTransactionalSession(this NServiceBus.PersistenceExtensions<NServiceBus.MongoPersistence> persistenceExtensions) { }
10+
public static NServiceBus.PersistenceExtensions<NServiceBus.MongoPersistence> EnableTransactionalSession(this NServiceBus.PersistenceExtensions<NServiceBus.MongoPersistence> persistenceExtensions, NServiceBus.TransactionalSession.TransactionalSessionOptions transactionalSessionOptions) { }
1011
public static System.Threading.Tasks.Task Open(this NServiceBus.TransactionalSession.ITransactionalSession session, System.Threading.CancellationToken cancellationToken = default) { }
1112
}
1213
}

src/NServiceBus.Storage.MongoDB.TransactionalSession/MongoTransactionalSessionExtensions.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace NServiceBus.TransactionalSession
22
{
3+
using System;
34
using System.Threading;
45
using System.Threading.Tasks;
56
using Features;
@@ -14,9 +15,22 @@ public static class MongoTransactionalSessionExtensions
1415
/// Enables transactional session for this endpoint.
1516
/// </summary>
1617
public static PersistenceExtensions<MongoPersistence> EnableTransactionalSession(
17-
this PersistenceExtensions<MongoPersistence> persistenceExtensions)
18+
this PersistenceExtensions<MongoPersistence> persistenceExtensions) =>
19+
EnableTransactionalSession(persistenceExtensions, new TransactionalSessionOptions());
20+
21+
/// <summary>
22+
/// Enables the transactional session for this endpoint using the specified TransactionalSessionOptions.
23+
/// </summary>
24+
public static PersistenceExtensions<MongoPersistence> EnableTransactionalSession(this PersistenceExtensions<MongoPersistence> persistenceExtensions,
25+
TransactionalSessionOptions transactionalSessionOptions)
1826
{
19-
persistenceExtensions.GetSettings().EnableFeatureByDefault<MongoTransactionalSession>();
27+
ArgumentNullException.ThrowIfNull(persistenceExtensions);
28+
ArgumentNullException.ThrowIfNull(transactionalSessionOptions);
29+
30+
var settings = persistenceExtensions.GetSettings();
31+
32+
settings.Set(transactionalSessionOptions);
33+
settings.EnableFeatureByDefault<MongoTransactionalSession>();
2034

2135
return persistenceExtensions;
2236
}

src/NServiceBus.Storage.MongoDB.TransactionalSession/NServiceBus.Storage.MongoDB.TransactionalSession.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</ItemGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="NServiceBus.TransactionalSession" Version="3.2.0" />
15+
<PackageReference Include="NServiceBus.TransactionalSession" Version="3.3.0" />
1616
<PackageReference Include="Particular.Packaging" Version="4.2.2" PrivateAssets="All" />
1717
</ItemGroup>
1818

0 commit comments

Comments
 (0)