Skip to content

Commit bab278d

Browse files
Merge pull request #1421 from Particular/tx-session-33
Add new configuration API for Transactional Session v3.3.0
2 parents 6c8541b + d0c727b commit bab278d

File tree

15 files changed

+228
-83
lines changed

15 files changed

+228
-83
lines changed

src/NServiceBus.RavenDB.Tests/ApprovalFiles/APIApprovals.ApproveRavenDBPersistence.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(@"NServiceBus.RavenDB.ClusterWide.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007f16e21368ff041183fab592d9e8ed37e7be355e93323147a1d29983d6e591b04282e4da0c9e18bd901e112c0033925eb7d7872c2f1706655891c5c9d57297994f707d16ee9a8f40d978f064ee1ffc73c0db3f4712691b23bf596f75130f4ec978cf78757ec034625a5f27e6bb50c618931ea49f6f628fd74271c32959efb1c5")]
22
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(@"NServiceBus.RavenDB.PersistenceTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007f16e21368ff041183fab592d9e8ed37e7be355e93323147a1d29983d6e591b04282e4da0c9e18bd901e112c0033925eb7d7872c2f1706655891c5c9d57297994f707d16ee9a8f40d978f064ee1ffc73c0db3f4712691b23bf596f75130f4ec978cf78757ec034625a5f27e6bb50c618931ea49f6f628fd74271c32959efb1c5")]
33
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(@"NServiceBus.RavenDB.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007f16e21368ff041183fab592d9e8ed37e7be355e93323147a1d29983d6e591b04282e4da0c9e18bd901e112c0033925eb7d7872c2f1706655891c5c9d57297994f707d16ee9a8f40d978f064ee1ffc73c0db3f4712691b23bf596f75130f4ec978cf78757ec034625a5f27e6bb50c618931ea49f6f628fd74271c32959efb1c5")]
4+
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(@"NServiceBus.RavenDB.TransactionalSession, PublicKey=0024000004800000940000000602000000240000525341310004000001000100dde965e6172e019ac82c2639ffe494dd2e7dd16347c34762a05732b492e110f2e4e2e1b5ef2d85c848ccfb671ee20a47c8d1376276708dc30a90ff1121b647ba3b7259a6bc383b2034938ef0e275b58b920375ac605076178123693c6c4f1331661a62eba28c249386855637780e3ff5f23a6d854700eaa6803ef48907513b92")]
45
namespace NServiceBus.Persistence.RavenDB
56
{
67
public interface IAsyncSessionProvider
@@ -20,6 +21,7 @@ namespace NServiceBus
2021
{
2122
public static class RavenDBOutboxExtensions
2223
{
24+
public static void EndpointName(this NServiceBus.Outbox.OutboxSettings configuration, string endpointName) { }
2325
public static void SetFrequencyToRunDeduplicationDataCleanup(this NServiceBus.Outbox.OutboxSettings configuration, System.TimeSpan frequencyToRunDeduplicationDataCleanup) { }
2426
public static void SetTimeToKeepDeduplicationData(this NServiceBus.Outbox.OutboxSettings configuration, System.TimeSpan timeToKeepDeduplicationData) { }
2527
}

src/NServiceBus.RavenDB.TransactionalSession.AcceptanceTests/Infrastructure/CaptureServiceProviderStartupTask.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@ namespace NServiceBus.TransactionalSession.AcceptanceTests
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: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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 endpointCustomization,
15+
Func<EndpointConfiguration, Task> configurationBuilderCustomization)
16+
{
17+
var endpointConfiguration = new EndpointConfiguration(endpointCustomization.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<RavenDBPersistence>();
31+
persistence.EnableTransactionalSession();
32+
persistence.SetDefaultDocumentStore(SetupFixture.DocumentStore);
33+
persistence.SetMessageToDatabaseMappingConvention(headers =>
34+
{
35+
if (headers.TryGetValue("tenant-id", out var tenantValue))
36+
{
37+
return tenantValue;
38+
}
39+
40+
return SetupFixture.DefaultDatabaseName;
41+
});
42+
43+
endpointConfiguration.GetSettings().Set(persistence);
44+
45+
if (runDescriptor.ScenarioContext is TransactionalSessionTestContext testContext)
46+
{
47+
endpointConfiguration.RegisterStartupTask(sp => new CaptureServiceProviderStartupTask(sp, testContext, endpointCustomization.EndpointName));
48+
}
49+
50+
await configurationBuilderCustomization(endpointConfiguration).ConfigureAwait(false);
51+
52+
// scan types at the end so that all types used by the configuration have been loaded into the AppDomain
53+
endpointConfiguration.TypesToIncludeInScan(endpointCustomization.GetTypesScopedByTestClass());
54+
55+
return endpointConfiguration;
56+
}
57+
}

src/NServiceBus.RavenDB.TransactionalSession.AcceptanceTests/Infrastructure/IInjectServiceProvider.cs

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

src/NServiceBus.RavenDB.TransactionalSession.AcceptanceTests/Infrastructure/TransactionSessionDefaultServer.cs

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,18 @@
11
namespace NServiceBus.TransactionalSession.AcceptanceTests
22
{
33
using System;
4-
using System.IO;
54
using System.Threading.Tasks;
6-
using AcceptanceTesting;
7-
using AcceptanceTesting.Customization;
85
using AcceptanceTesting.Support;
9-
using NUnit.Framework;
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 endpointCustomization,
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(endpointCustomization.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 persistence = endpointConfiguration.UsePersistence<RavenDBPersistence>();
33-
persistence.EnableTransactionalSession();
34-
persistence.SetDefaultDocumentStore(SetupFixture.DocumentStore);
35-
persistence.SetMessageToDatabaseMappingConvention(headers =>
36-
{
37-
if (headers.TryGetValue("tenant-id", out var tenantValue))
38-
{
39-
return tenantValue;
40-
}
41-
42-
return SetupFixture.DefaultDatabaseName;
43-
});
44-
45-
endpointConfiguration.RegisterStartupTask(sp => new CaptureServiceProviderStartupTask(sp, runDescriptor.ScenarioContext));
46-
47-
await configurationBuilderCustomization(endpointConfiguration).ConfigureAwait(false);
48-
49-
// scan types at the end so that all types used by the configuration have been loaded into the AppDomain
50-
endpointConfiguration.TypesToIncludeInScan(endpointCustomization.GetTypesScopedByTestClass());
14+
endpointConfiguration.GetSettings().Get<PersistenceExtensions<RavenDBPersistence>>()
15+
.EnableTransactionalSession();
5116

5217
return endpointConfiguration;
5318
}
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 RavenDbOpenSessionOptions());
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<RavenDBPersistence>>();
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.RavenDB.TransactionalSession.AcceptanceTests/When_using_outbox_with_multitenancy.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,8 @@ public async Task Should_store_data_on_correct_tenant()
3939
Assert.That(context.Document.SessionId, Is.EqualTo(context.SessionId), "should have loaded the document from the correct tenant database");
4040
}
4141

42-
public class Context : ScenarioContext, IInjectServiceProvider
42+
public class Context : TransactionalSessionTestContext
4343
{
44-
public IServiceProvider ServiceProvider { get; set; }
45-
4644
public bool MessageReceived { get; set; }
4745
public TestDocument Document { get; set; }
4846
public string SessionId { get; set; }
@@ -52,18 +50,14 @@ public class MultitenantEndpoint : EndpointConfigurationBuilder
5250
{
5351
public MultitenantEndpoint() => EndpointSetup<TransactionSessionWithOutboxEndpoint>();
5452

55-
public class SampleMessageHandler : IHandleMessages<SampleMessage>
53+
public class SampleMessageHandler(Context testContext) : IHandleMessages<SampleMessage>
5654
{
57-
public SampleMessageHandler(Context testContext) => this.testContext = testContext;
58-
5955
public async Task Handle(SampleMessage message, IMessageHandlerContext context)
6056
{
6157
testContext.MessageReceived = true;
6258
var ravenSession = context.SynchronizedStorageSession.RavenSession();
6359
testContext.Document = await ravenSession.LoadAsync<TestDocument>(message.DocumentId);
6460
}
65-
66-
readonly Context testContext;
6761
}
6862
}
6963

src/NServiceBus.RavenDB.TransactionalSession.AcceptanceTests/When_using_transactional_session.cs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,10 @@ public async Task Should_send_immediate_dispatch_messages_even_if_session_is_not
129129
Assert.That(result.MessageReceived, Is.True);
130130
}
131131

132-
class Context : ScenarioContext, IInjectServiceProvider
132+
class Context : TransactionalSessionTestContext
133133
{
134134
public bool MessageReceived { get; set; }
135135
public bool CompleteMessageReceived { get; set; }
136-
public IServiceProvider ServiceProvider { get; set; }
137136
public string SessionId { get; set; }
138137
}
139138

@@ -151,32 +150,24 @@ public AnEndpoint()
151150
}
152151
}
153152

154-
class SampleHandler : IHandleMessages<SampleMessage>
153+
class SampleHandler(Context testContext) : IHandleMessages<SampleMessage>
155154
{
156-
public SampleHandler(Context testContext) => this.testContext = testContext;
157-
158155
public Task Handle(SampleMessage message, IMessageHandlerContext context)
159156
{
160157
testContext.MessageReceived = true;
161158

162159
return Task.CompletedTask;
163160
}
164-
165-
readonly Context testContext;
166161
}
167162

168-
class CompleteTestMessageHandler : IHandleMessages<CompleteTestMessage>
163+
class CompleteTestMessageHandler(Context testContext) : IHandleMessages<CompleteTestMessage>
169164
{
170-
public CompleteTestMessageHandler(Context context) => testContext = context;
171-
172165
public Task Handle(CompleteTestMessage message, IMessageHandlerContext context)
173166
{
174167
testContext.CompleteMessageReceived = true;
175168

176169
return Task.CompletedTask;
177170
}
178-
179-
readonly Context testContext;
180171
}
181172
}
182173

src/NServiceBus.RavenDB.TransactionalSession.Tests/ApprovalFiles/APIApprovals.Approve.approved.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ namespace NServiceBus.TransactionalSession
77
public static class RavenDbTransactionalSessionExtensions
88
{
99
public static NServiceBus.PersistenceExtensions<NServiceBus.RavenDBPersistence> EnableTransactionalSession(this NServiceBus.PersistenceExtensions<NServiceBus.RavenDBPersistence> persistenceExtensions) { }
10+
public static NServiceBus.PersistenceExtensions<NServiceBus.RavenDBPersistence> EnableTransactionalSession(this NServiceBus.PersistenceExtensions<NServiceBus.RavenDBPersistence> persistenceExtensions, NServiceBus.TransactionalSession.TransactionalSessionOptions transactionalSessionOptions) { }
1011
}
1112
}

0 commit comments

Comments
 (0)