Skip to content

Commit 137b8b9

Browse files
committed
Make SendOnlyInterface a separate concept entirely
1 parent f70993a commit 137b8b9

File tree

7 files changed

+128
-39
lines changed

7 files changed

+128
-39
lines changed

src/AcceptanceTesting/SubscriptionHelper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,10 @@ public static class SubscriptionHelper
88
interfaceConfig.EnableMessageDrivenPublishSubscribe(new InMemorySubscriptionStorage());
99
return interfaceConfig;
1010
}
11+
12+
public static SendOnlyInterfaceConfiguration<T> InMemorySubscriptions<T>(this SendOnlyInterfaceConfiguration<T> interfaceConfig) where T : TransportDefinition, new()
13+
{
14+
interfaceConfig.EnableMessageDrivenPublishSubscribe(new InMemorySubscriptionStorage());
15+
return interfaceConfig;
16+
}
1117
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System.Threading.Tasks;
2+
using NServiceBus.AcceptanceTesting;
3+
using NServiceBus.AcceptanceTests;
4+
using NServiceBus.AcceptanceTests.EndpointTemplates;
5+
using NUnit.Framework;
6+
7+
namespace NServiceBus.Router.AcceptanceTests.SingleRouter
8+
{
9+
using AcceptanceTesting.Customization;
10+
11+
[TestFixture]
12+
public class When_forwarding_a_message_via_sendonly_router : NServiceBusAcceptanceTest
13+
{
14+
[Test]
15+
public async Task Should_deliver_the_message()
16+
{
17+
var result = await Scenario.Define<Context>()
18+
.WithRouter("Router", cfg =>
19+
{
20+
cfg.AddInterface<TestTransport>("Left", t => t.BrokerAlpha()).InMemorySubscriptions();
21+
cfg.AddSendOnlyInterface<TestTransport>("Right", t => t.BrokerBravo()).InMemorySubscriptions();
22+
23+
cfg.UseStaticRoutingProtocol().AddForwardRoute("Left", "Right");
24+
})
25+
.WithEndpoint<Sender>(c => c.When(s => s.Send(new MyRequest())))
26+
.WithEndpoint<Receiver>()
27+
.Done(c => c.RequestReceived)
28+
.Run();
29+
30+
Assert.IsTrue(result.RequestReceived);
31+
}
32+
33+
class Context : ScenarioContext
34+
{
35+
public bool RequestReceived { get; set; }
36+
}
37+
38+
class Sender : EndpointConfigurationBuilder
39+
{
40+
public Sender()
41+
{
42+
EndpointSetup<DefaultServer>(c =>
43+
{
44+
var routing = c.UseTransport<TestTransport>().BrokerAlpha().Routing();
45+
var bridge = routing.ConnectToRouter("Router");
46+
bridge.RouteToEndpoint(typeof(MyRequest), Conventions.EndpointNamingConvention(typeof(Receiver)));
47+
});
48+
}
49+
}
50+
51+
class Receiver : EndpointConfigurationBuilder
52+
{
53+
public Receiver()
54+
{
55+
EndpointSetup<DefaultServer>(c =>
56+
{
57+
//No bridge configuration needed for reply
58+
c.UseTransport<TestTransport>().BrokerBravo();
59+
});
60+
}
61+
62+
class MyRequestHandler : IHandleMessages<MyRequest>
63+
{
64+
Context scenarioContext;
65+
66+
public MyRequestHandler(Context scenarioContext)
67+
{
68+
this.scenarioContext = scenarioContext;
69+
}
70+
71+
public Task Handle(MyRequest request, IMessageHandlerContext context)
72+
{
73+
scenarioContext.RequestReceived = true;
74+
return Task.CompletedTask;
75+
}
76+
}
77+
}
78+
79+
class MyRequest : IMessage
80+
{
81+
}
82+
}
83+
}

src/NServiceBus.Router/Router.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ public static IRouter Create(RouterConfiguration config)
2828
feature.Configure(config);
2929
}
3030

31+
var sendOnlyInterfaces = config.SendOnlyInterfaceFactories.Select(x => x()).ToArray();
3132
var interfaces = config.InterfaceFactories.Select(x => x()).ToArray();
33+
var allInterfaceNames = sendOnlyInterfaces.Select(i => i.Name).Concat(interfaces.Select(i => i.Name)).ToArray();
3234

3335
var chains = config.Chains;
3436

@@ -61,7 +63,7 @@ public static IRouter Create(RouterConfiguration config)
6163

6264
chains.AddRule(_ => new PreroutingToPublishPreroutingFork());
6365
chains.AddChain(cb => cb.Begin<PublishPreroutingContext>().Terminate());
64-
chains.AddRule(c => new PublishPreroutingTerminator(interfaces.Select(i => i.Name).ToArray(), c.TypeGenerator));
66+
chains.AddRule(c => new PublishPreroutingTerminator(allInterfaceNames, c.TypeGenerator));
6567
chains.AddChain(cb => cb.Begin<ForwardPublishContext>().Terminate());
6668

6769
chains.AddRule(_ => new PreroutingToReplyPreroutingFork());
@@ -80,7 +82,7 @@ public static IRouter Create(RouterConfiguration config)
8082
chains.AddChain(cb => cb.Begin<PostroutingContext>().Terminate());
8183
chains.AddRule(c => new PostroutingTerminator(c.Endpoint));
8284

83-
return new RouterImpl(config.Name, interfaces, config.Modules.ToArray(), config.RoutingProtocol, chains, config.Settings);
85+
return new RouterImpl(config.Name, interfaces, sendOnlyInterfaces, config.Modules.ToArray(), config.RoutingProtocol, chains, config.Settings);
8486
}
8587
}
8688
}

src/NServiceBus.Router/RouterConfiguration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ public SendOnlyInterfaceConfiguration<T> AddSendOnlyInterface<T>(string name, Ac
5353
where T : TransportDefinition, new()
5454
{
5555
var ifaceConfig = new SendOnlyInterfaceConfiguration<T>(name, customization, this);
56-
InterfaceFactories.Add(() => CreateSendOnlyInterface(ifaceConfig));
56+
SendOnlyInterfaceFactories.Add(() => CreateSendOnlyInterface(ifaceConfig));
5757
return ifaceConfig;
5858
}
5959

60-
Interface CreateSendOnlyInterface<T>(SendOnlyInterfaceConfiguration<T> ifaceConfig)
60+
SendOnlyInterface CreateSendOnlyInterface<T>(SendOnlyInterfaceConfiguration<T> ifaceConfig)
6161
where T : TransportDefinition, new()
6262
{
6363
return ifaceConfig.Create(Name, typeGenerator, Settings);
@@ -148,6 +148,7 @@ public void DefineChain<TInput>(Func<ChainBuilder, IChain<TInput>> chainDefiniti
148148
bool? autoCreateQueues;
149149
string autoCreateQueuesIdentity;
150150
internal List<Func<Interface>> InterfaceFactories = new List<Func<Interface>>();
151+
internal List<Func<SendOnlyInterface>> SendOnlyInterfaceFactories = new List<Func<SendOnlyInterface>>();
151152
internal List<IModule> Modules = new List<IModule>();
152153
internal HashSet<Type> Features = new HashSet<Type>();
153154
internal IRoutingProtocol RoutingProtocol;

src/NServiceBus.Router/RouterImpl.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Linq;
43
using System.Threading.Tasks;
54
using NServiceBus.Logging;
65
using NServiceBus.Router;
76

87
class RouterImpl : IRouter
98
{
10-
public RouterImpl(string name, Interface[] interfaces, IModule[] modules, IRoutingProtocol routingProtocol, InterfaceChains interfaceChains, SettingsHolder extensibilitySettings)
9+
public RouterImpl(string name, Interface[] interfaces, SendOnlyInterface[] sendOnlyInterfaces, IModule[] modules, IRoutingProtocol routingProtocol, InterfaceChains interfaceChains, SettingsHolder extensibilitySettings)
1110
{
1211
this.name = name;
12+
this.sendOnlyInterfaces = sendOnlyInterfaces;
1313
this.modules = modules;
1414
this.routingProtocol = routingProtocol;
1515
this.interfaceChains = interfaceChains;
1616
this.extensibilitySettings = extensibilitySettings;
17-
this.interfaces = interfaces.ToDictionary(x => x.Name, x => x);
17+
this.interfaces = interfaces;
1818
}
1919

2020
public async Task Initialize()
@@ -25,9 +25,14 @@ public async Task Initialize()
2525
}
2626

2727
rootContext = new RootContext(interfaceChains, name);
28-
await routingProtocol.Start(new RouterMetadata(name, interfaces.Keys.ToList())).ConfigureAwait(false);
28+
await routingProtocol.Start(new RouterMetadata(name, interfaces.Select(i => i.Name).ToList())).ConfigureAwait(false);
2929

30-
foreach (var iface in interfaces.Values)
30+
foreach (var iface in sendOnlyInterfaces)
31+
{
32+
await iface.Initialize(interfaceChains).ConfigureAwait(false);
33+
}
34+
35+
foreach (var iface in interfaces)
3136
{
3237
await iface.Initialize(interfaceChains, rootContext).ConfigureAwait(false);
3338
}
@@ -50,12 +55,12 @@ public async Task Start()
5055
log.Debug($"Started module {module}");
5156
}
5257

53-
await Task.WhenAll(interfaces.Values.Select(p => p.StartReceiving())).ConfigureAwait(false);
58+
await Task.WhenAll(interfaces.Select(p => p.StartReceiving())).ConfigureAwait(false);
5459
}
5560

5661
public async Task Stop()
5762
{
58-
await Task.WhenAll(interfaces.Values.Select(s => s.StopReceiving())).ConfigureAwait(false);
63+
await Task.WhenAll(interfaces.Select(s => s.StopReceiving())).ConfigureAwait(false);
5964

6065
//Stop modules in reverse order
6166
foreach (var module in modules.Reverse())
@@ -65,17 +70,19 @@ public async Task Stop()
6570
log.Debug($"Stopped module {module}");
6671
}
6772

68-
await Task.WhenAll(interfaces.Values.Select(s => s.Stop())).ConfigureAwait(false);
73+
await Task.WhenAll(interfaces.Select(s => s.Stop())).ConfigureAwait(false);
74+
await Task.WhenAll(sendOnlyInterfaces.Select(s => s.Stop())).ConfigureAwait(false);
6975
await routingProtocol.Stop().ConfigureAwait(false);
7076
}
7177

7278
bool initialized;
7379
string name;
80+
Interface[] interfaces;
81+
SendOnlyInterface[] sendOnlyInterfaces;
7482
IModule[] modules;
7583
IRoutingProtocol routingProtocol;
7684
InterfaceChains interfaceChains;
7785
SettingsHolder extensibilitySettings;
78-
Dictionary<string, Interface> interfaces;
7986
static ILog log = LogManager.GetLogger<RouterImpl>();
8087
RootContext rootContext;
8188
}

src/NServiceBus.Router/SendOnlyInterface.cs

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@
66
using NServiceBus.Raw;
77
using NServiceBus.Transport;
88

9-
class SendOnlyInterface<T> : Interface where T : TransportDefinition, new()
9+
interface SendOnlyInterface
10+
{
11+
string Name { get; }
12+
Task Initialize(InterfaceChains interfaces);
13+
Task Stop();
14+
}
15+
16+
class SendOnlyInterface<T> : SendOnlyInterface where T : TransportDefinition, new()
1017
{
1118
public SendOnlyInterface(string endpointName, string interfaceName, Action<TransportExtensions<T>> transportCustomization, Func<IRawEndpoint, IRuleCreationContext> ruleCreationContextFactory)
1219
{
@@ -26,44 +33,27 @@ static void SetTransportSpecificFlags(NServiceBus.Settings.SettingsHolder settin
2633
settings.Set("RabbitMQ.RoutingTopologySupportsDelayedDelivery", true);
2734
}
2835

29-
public async Task Initialize(InterfaceChains interfaces, RootContext rootContext)
36+
public async Task Initialize(InterfaceChains interfaces)
3037
{
31-
startable = await RawEndpoint.Create(config).ConfigureAwait(false);
38+
var startable = await RawEndpoint.Create(config).ConfigureAwait(false);
3239
config = null;
3340
var ruleCreationContext = ruleCreationContextFactory(startable);
3441
interfaces.InitializeInterface(Name, ruleCreationContext);
35-
}
36-
37-
public async Task StartReceiving()
38-
{
39-
receiver = await startable.Start().ConfigureAwait(false);
40-
}
4142

42-
public async Task StopReceiving()
43-
{
44-
if (receiver != null)
45-
{
46-
stoppable = await receiver.StopReceiving().ConfigureAwait(false);
47-
}
48-
else
49-
{
50-
stoppable = null;
51-
}
43+
endpoint = await startable.Start().ConfigureAwait(false);
5244
}
5345

5446
public async Task Stop()
5547
{
56-
if (stoppable != null)
48+
if (endpoint != null)
5749
{
58-
await stoppable.Stop().ConfigureAwait(false);
59-
stoppable = null;
50+
await endpoint.Stop().ConfigureAwait(false);
51+
endpoint = null;
6052
}
6153
}
6254

6355
RawEndpointConfiguration config;
64-
IStartableRawEndpoint startable;
65-
IReceivingRawEndpoint receiver;
66-
IStoppableRawEndpoint stoppable;
56+
IStoppableRawEndpoint endpoint;
6757

6858
Func<IRawEndpoint, IRuleCreationContext> ruleCreationContextFactory;
6959
}

src/NServiceBus.Router/SendOnlyInterfaceConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public void OverrideEndpointName(string interfaceEndpointName)
8585
/// </summary>
8686
public EndpointInstances EndpointInstances { get; } = new EndpointInstances();
8787

88-
internal Interface Create(string endpointName, RuntimeTypeGenerator typeGenerator, SettingsHolder routerSettings)
88+
internal SendOnlyInterface Create(string endpointName, RuntimeTypeGenerator typeGenerator, SettingsHolder routerSettings)
8989
{
9090
IRuleCreationContext ContextFactory(IRawEndpoint e)
9191
{

0 commit comments

Comments
 (0)