Skip to content

Commit 9bb1bf2

Browse files
Merge pull request #7258 from Particular/publisher-metadata
Consistently use PublisherMetadata to facilitate endpoint setup in Azure Service Bus
2 parents 5632b27 + fa0c755 commit 9bb1bf2

File tree

54 files changed

+250
-188
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+250
-188
lines changed

src/NServiceBus.AcceptanceTesting/Customization/EndpointConfigurationExtensions.cs

+8
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,12 @@ public static void RouteToEndpoint(this RoutingSettings routingSettings, Type me
7676
var destinationEndpointAddress = Conventions.EndpointNamingConvention(destinationEndpointType);
7777
routingSettings.RouteToEndpoint(messageType, destinationEndpointAddress);
7878
}
79+
80+
public static void EnforcePublisherMetadataRegistration(this EndpointConfiguration config, string endpointName, PublisherMetadata publisherMetadata)
81+
{
82+
config.Pipeline.Register(new EnforcePublisherMetadataBehavior(endpointName, publisherMetadata),
83+
"Enforces all published events have corresponding mappings in the PublisherMetadata");
84+
config.Pipeline.Register(new EnforceSubscriptionPublisherMetadataBehavior(endpointName, publisherMetadata),
85+
"Enforces all subscribed events have corresponding mappings in the PublisherMetadata");
86+
}
7987
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace NServiceBus.AcceptanceTesting.Support;
2+
3+
using System;
4+
using System.Threading.Tasks;
5+
using Pipeline;
6+
7+
public class EnforcePublisherMetadataBehavior(string endpointName, PublisherMetadata publisherMetadata) : IBehavior<IOutgoingPublishContext, IOutgoingPublishContext>
8+
{
9+
public Task Invoke(IOutgoingPublishContext context, Func<IOutgoingPublishContext, Task> next)
10+
{
11+
var publisherDetails = publisherMetadata[endpointName];
12+
if (!publisherDetails.Events.Contains(context.Message.MessageType))
13+
{
14+
throw new Exception($"The event '{context.Message.MessageType}' being published by '{endpointName}' does not have a corresponding mapping in the PublisherMetadata. Add the following code to the endpoint configuration builder: metadata.RegisterSelfAsPublisherFor<{context.Message.MessageType}>(this);");
15+
}
16+
return next(context);
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace NServiceBus.AcceptanceTesting.Support;
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Pipeline;
9+
10+
public class EnforceSubscriptionPublisherMetadataBehavior(string endpointName, PublisherMetadata publisherMetadata) : IBehavior<ISubscribeContext, ISubscribeContext>
11+
{
12+
readonly HashSet<Type> eventTypeMap = publisherMetadata.Publishers.SelectMany(publisher => publisher.Events).ToHashSet();
13+
14+
public Task Invoke(ISubscribeContext context, Func<ISubscribeContext, Task> next)
15+
{
16+
var unmappedEventTypes = new List<Type>(context.EventTypes.Where(eventType => !eventTypeMap.Contains(eventType)));
17+
if (unmappedEventTypes.Count == 0)
18+
{
19+
return next(context);
20+
}
21+
22+
var builder = new StringBuilder();
23+
_ = builder.AppendLine($"The following event(s) are being subscribed to by '{endpointName}' but do not have a corresponding mapping in the PublisherMetadata:");
24+
foreach (var eventType in unmappedEventTypes)
25+
{
26+
_ = builder.AppendLine($"- metadata.RegisterPublisherFor<{eventType}>(\"typeof(PublisherEndpointToBeDetermined)\");");
27+
}
28+
throw new Exception(builder.ToString());
29+
}
30+
}

src/NServiceBus.AcceptanceTesting/Support/PublisherMetadata.cs

+17-19
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,31 @@ public void RegisterPublisherFor<T>(string endpointName)
2323
publisher.RegisterOwnedEvent<T>();
2424
}
2525

26-
public void RegisterPublisherFor<T>(Type endpointType)
27-
{
28-
RegisterPublisherFor<T>(Conventions.EndpointNamingConvention(endpointType));
29-
}
26+
public void RegisterSelfAsPublisherFor<TEventType>(EndpointConfigurationBuilder self) =>
27+
RegisterPublisherFor<TEventType>(Conventions.EndpointNamingConvention(self.GetType()));
3028

31-
Dictionary<string, PublisherDetails> publisherDetails = [];
29+
public void RegisterPublisherFor<TEventType, TPublisher>() where TPublisher : EndpointConfigurationBuilder =>
30+
RegisterPublisherFor<TEventType>(Conventions.EndpointNamingConvention(typeof(TPublisher)));
3231

33-
public class PublisherDetails
34-
{
35-
public PublisherDetails(string publisherName)
36-
{
37-
PublisherName = publisherName;
38-
}
32+
public void RegisterPublisherFor<TEventType>(Type endpointType) =>
33+
RegisterPublisherFor<TEventType>(Conventions.EndpointNamingConvention(endpointType));
3934

40-
public List<Type> Events { get; } = [];
35+
public PublisherDetails this[string publisherName] =>
36+
publisherDetails.TryGetValue(publisherName, out var publisherDetail)
37+
? publisherDetail
38+
: new PublisherDetails(publisherName);
4139

42-
public string PublisherName { get; }
40+
readonly Dictionary<string, PublisherDetails> publisherDetails = [];
41+
42+
public class PublisherDetails(string publisherName)
43+
{
44+
public HashSet<Type> Events { get; } = [];
45+
46+
public string PublisherName { get; } = publisherName;
4347

4448
public void RegisterOwnedEvent<T>()
4549
{
4650
var eventType = typeof(T);
47-
48-
if (Events.Contains(eventType))
49-
{
50-
return;
51-
}
52-
5351
Events.Add(eventType);
5452
}
5553
}

src/NServiceBus.AcceptanceTests/ConfigureEndpointAcceptanceTestingTransport.cs

+20-24
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
using System;
44
using System.IO;
55
using System.Threading.Tasks;
6+
using AcceptanceTesting.Customization;
67
using NServiceBus;
78
using NServiceBus.AcceptanceTesting.Support;
89
using NUnit.Framework;
910

10-
public class ConfigureEndpointAcceptanceTestingTransport : IConfigureEndpointTestExecution
11+
public class ConfigureEndpointAcceptanceTestingTransport(
12+
bool useNativePubSub,
13+
bool useNativeDelayedDelivery,
14+
TransportTransactionMode? transactionMode = null,
15+
bool? enforcePublisherMetadata = null)
16+
: IConfigureEndpointTestExecution
1117
{
12-
public ConfigureEndpointAcceptanceTestingTransport(bool useNativePubSub, bool useNativeDelayedDelivery, TransportTransactionMode? transactionMode = null)
13-
{
14-
this.useNativePubSub = useNativePubSub;
15-
this.useNativeDelayedDelivery = useNativeDelayedDelivery;
16-
this.transactionMode = transactionMode;
17-
}
18-
1918
public Task Cleanup()
2019
{
2120
try
@@ -25,26 +24,22 @@ public Task Cleanup()
2524
Directory.Delete(storageDir, true);
2625
}
2726
}
28-
catch { }
27+
catch
28+
{
29+
// ignored
30+
}
2931

3032
return Task.CompletedTask;
3133
}
3234

33-
public Task Configure(string endpointName, EndpointConfiguration configuration, RunSettings settings, PublisherMetadata publisherMetadata)
35+
public Task Configure(string endpointName, EndpointConfiguration configuration, RunSettings settings,
36+
PublisherMetadata publisherMetadata)
3437
{
3538
var testRunId = TestContext.CurrentContext.Test.ID;
3639

37-
string tempDir;
38-
39-
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
40-
{
40+
string tempDir =
4141
//can't use bin dir since that will be too long on the build agents
42-
tempDir = @"c:\temp";
43-
}
44-
else
45-
{
46-
tempDir = Path.GetTempPath();
47-
}
42+
Environment.OSVersion.Platform == PlatformID.Win32NT ? @"c:\temp" : Path.GetTempPath();
4843

4944
storageDir = Path.Combine(tempDir, "acc", testRunId);
5045

@@ -60,6 +55,11 @@ public Task Configure(string endpointName, EndpointConfiguration configuration,
6055
acceptanceTestingTransport.TransportTransactionMode = transactionMode.Value;
6156
}
6257

58+
if (enforcePublisherMetadata.GetValueOrDefault(false))
59+
{
60+
configuration.EnforcePublisherMetadataRegistration(endpointName, publisherMetadata);
61+
}
62+
6363
var routing = configuration.UseTransport(acceptanceTestingTransport);
6464

6565
if (!useNativePubSub)
@@ -77,9 +77,5 @@ public Task Configure(string endpointName, EndpointConfiguration configuration,
7777
return Task.CompletedTask;
7878
}
7979

80-
readonly bool useNativePubSub;
81-
readonly bool useNativeDelayedDelivery;
82-
readonly TransportTransactionMode? transactionMode;
83-
8480
string storageDir;
8581
}

src/NServiceBus.AcceptanceTests/Core/AutomaticSubscriptions/When_excluding_event_type_from_autosubscribe.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public Subscriber()
5050
},
5151
metadata =>
5252
{
53-
metadata.RegisterPublisherFor<EventToSubscribeTo>(typeof(Subscriber));
54-
metadata.RegisterPublisherFor<EventToExclude>(typeof(Subscriber));
53+
metadata.RegisterPublisherFor<EventToSubscribeTo, Subscriber>();
54+
metadata.RegisterPublisherFor<EventToExclude, Subscriber>();
5555
});
5656
}
5757

src/NServiceBus.AcceptanceTests/Core/AutomaticSubscriptions/When_starting_an_endpoint_with_a_saga.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ public Subscriber()
4040
EndpointSetup<DefaultServer>((c, r) => c.Pipeline.Register("SubscriptionSpy", new SubscriptionSpy((Context)r.ScenarioContext), "Spies on subscriptions made"),
4141
metadata =>
4242
{
43-
metadata.RegisterPublisherFor<MyEventBase>(typeof(Subscriber));
44-
metadata.RegisterPublisherFor<MyEvent>(typeof(Subscriber));
43+
metadata.RegisterPublisherFor<MyEventBase, Subscriber>();
44+
metadata.RegisterPublisherFor<MyEvent, Subscriber>();
4545
});
4646
}
4747

src/NServiceBus.AcceptanceTests/Core/AutomaticSubscriptions/When_starting_an_endpoint_with_a_saga_autosubscribe_disabled.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ public Subscriber()
4343
},
4444
metadata =>
4545
{
46-
metadata.RegisterPublisherFor<MyEventWithParent>(typeof(Subscriber));
47-
metadata.RegisterPublisherFor<MyEvent>(typeof(Subscriber));
46+
metadata.RegisterPublisherFor<MyEventWithParent, Subscriber>();
47+
metadata.RegisterPublisherFor<MyEvent, Subscriber>();
4848
});
4949
}
5050

src/NServiceBus.AcceptanceTests/Core/AutomaticSubscriptions/When_starting_an_endpoint_with_autosubscribe.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ public Subscriber()
5656
},
5757
metadata =>
5858
{
59-
metadata.RegisterPublisherFor<MyEvent>(typeof(Subscriber));
60-
metadata.RegisterPublisherFor<MyEventWithNoHandler>(typeof(Subscriber));
59+
metadata.RegisterPublisherFor<MyEvent, Subscriber>();
60+
metadata.RegisterPublisherFor<MyEventWithNoHandler, Subscriber>();
6161
});
6262
}
6363

src/NServiceBus.AcceptanceTests/Core/OpenTelemetry/Traces/When_incoming_event_has_trace.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public Subscriber() =>
8888
},
8989
metadata =>
9090
{
91-
metadata.RegisterPublisherFor<SomeEvent>(typeof(Publisher));
91+
metadata.RegisterPublisherFor<SomeEvent, Publisher>();
9292
});
9393

9494
public class ThisHandlesSomethingHandler : IHandleMessages<SomeEvent>

src/NServiceBus.AcceptanceTests/Core/OpenTelemetry/Traces/When_publishing_messages.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public Subscriber() =>
165165
},
166166
metadata =>
167167
{
168-
metadata.RegisterPublisherFor<ThisIsAnEvent>(typeof(Publisher));
168+
metadata.RegisterPublisherFor<ThisIsAnEvent, Publisher>();
169169
});
170170

171171
public class ThisHandlesSomethingHandler : IHandleMessages<ThisIsAnEvent>

src/NServiceBus.AcceptanceTests/Core/OpenTelemetry/Traces/When_subscribing.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class SubscribingEndpoint : EndpointConfigurationBuilder
7373
{
7474
public SubscribingEndpoint() => EndpointSetup<OpenTelemetryEnabledEndpoint>(
7575
c => c.DisableFeature<AutoSubscribe>(),
76-
p => p.RegisterPublisherFor<DemoEvent>(typeof(PublishingEndpoint)));
76+
p => p.RegisterPublisherFor<DemoEvent, PublishingEndpoint>());
7777
}
7878

7979
class PublishingEndpoint : EndpointConfigurationBuilder

src/NServiceBus.AcceptanceTests/Core/OpenTelemetry/Traces/When_unsubscribing.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class SubscriberEndpoint : EndpointConfigurationBuilder
7272
{
7373
public SubscriberEndpoint() => EndpointSetup<OpenTelemetryEnabledEndpoint>(
7474
c => c.DisableFeature<AutoSubscribe>(),
75-
p => p.RegisterPublisherFor<DemoEvent>(typeof(PublishingEndpoint)));
75+
p => p.RegisterPublisherFor<DemoEvent, PublishingEndpoint>());
7676
}
7777

7878
class PublishingEndpoint : EndpointConfigurationBuilder

src/NServiceBus.AcceptanceTests/Core/Pipeline/When_extending_the_publish_api.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public class Subscriber1 : EndpointConfigurationBuilder
8888
{
8989
public Subscriber1()
9090
{
91-
EndpointSetup<DefaultServer>(builder => builder.DisableFeature<AutoSubscribe>(), metadata => metadata.RegisterPublisherFor<MyEvent>(typeof(Publisher)));
91+
EndpointSetup<DefaultServer>(builder => builder.DisableFeature<AutoSubscribe>(), metadata => metadata.RegisterPublisherFor<MyEvent, Publisher>());
9292
}
9393

9494
public class MyHandler : IHandleMessages<MyEvent>

src/NServiceBus.AcceptanceTests/Core/PublishSubscribe/When_configuring_subscription_authorizer.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public Subscriber()
5858
routingSettings.DisablePublishing();
5959
}, p =>
6060
{
61-
p.RegisterPublisherFor<ForbiddenEvent>(typeof(PublisherWithAuthorizer));
62-
p.RegisterPublisherFor<AllowedEvent>(typeof(PublisherWithAuthorizer));
61+
p.RegisterPublisherFor<ForbiddenEvent, PublisherWithAuthorizer>();
62+
p.RegisterPublisherFor<AllowedEvent, PublisherWithAuthorizer>();
6363
});
6464
}
6565
}

src/NServiceBus.AcceptanceTests/Core/PublishSubscribe/When_disabling_publishing.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public EndpointWithDisabledPublishing()
6262
var routingSettings = new RoutingSettings<AcceptanceTestingTransport>(c.GetSettings());
6363
routingSettings.DisablePublishing();
6464
},
65-
pm => pm.RegisterPublisherFor<TestEvent>(typeof(MessageDrivenPublisher)));
65+
pm => pm.RegisterPublisherFor<TestEvent, MessageDrivenPublisher>());
6666
}
6767

6868
class EventHandler : IHandleMessages<TestEvent>

src/NServiceBus.AcceptanceTests/Core/Routing/AutomaticSubscriptions/When_handling_local_event.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public PublisherAndSubscriber()
5050
context.EventSubscribed = true;
5151
}
5252
});
53-
}, metadata => metadata.RegisterPublisherFor<Event>(typeof(PublisherAndSubscriber)));
53+
}, metadata => metadata.RegisterPublisherFor<Event, PublisherAndSubscriber>());
5454
}
5555

5656
public class Handler : IHandleMessages<Event>

src/NServiceBus.AcceptanceTests/Routing/MessageDrivenSubscriptions/Extend_event_routing.cs src/NServiceBus.AcceptanceTests/Core/Routing/MessageDrivenSubscriptions/Extend_event_routing.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
namespace NServiceBus.AcceptanceTests.Routing.MessageDrivenSubscriptions;
1+
namespace NServiceBus.AcceptanceTests.Core.Routing.MessageDrivenSubscriptions;
22

33
using System.Threading.Tasks;
4-
using AcceptanceTesting;
5-
using AcceptanceTesting.Customization;
6-
using Configuration.AdvancedExtensibility;
7-
using EndpointTemplates;
8-
using Features;
4+
using NServiceBus.AcceptanceTesting;
5+
using NServiceBus.AcceptanceTesting.Customization;
6+
using NServiceBus.AcceptanceTests.EndpointTemplates;
7+
using NServiceBus.Configuration.AdvancedExtensibility;
8+
using NServiceBus.Features;
99
using NServiceBus.Routing.MessageDrivenSubscriptions;
1010
using NUnit.Framework;
1111

src/NServiceBus.AcceptanceTests/Routing/MessageDrivenSubscriptions/Missing_pub_info.cs src/NServiceBus.AcceptanceTests/Core/Routing/MessageDrivenSubscriptions/Missing_pub_info.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
namespace NServiceBus.AcceptanceTests.Routing.MessageDrivenSubscriptions;
1+
namespace NServiceBus.AcceptanceTests.Core.Routing.MessageDrivenSubscriptions;
22

33
using System.Linq;
44
using System.Threading.Tasks;
5-
using AcceptanceTesting;
6-
using EndpointTemplates;
7-
using Features;
8-
using Logging;
5+
using NServiceBus.AcceptanceTesting;
6+
using NServiceBus.AcceptanceTests.EndpointTemplates;
7+
using NServiceBus.Features;
8+
using NServiceBus.Logging;
99
using NUnit.Framework;
1010

1111
public class Missing_pub_info : NServiceBusAcceptanceTest

src/NServiceBus.AcceptanceTests/Routing/MessageDrivenSubscriptions/Pub_from_sendonly.cs src/NServiceBus.AcceptanceTests/Core/Routing/MessageDrivenSubscriptions/Pub_from_sendonly.cs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
namespace NServiceBus.AcceptanceTests.Routing.MessageDrivenSubscriptions;
1+
namespace NServiceBus.AcceptanceTests.Core.Routing.MessageDrivenSubscriptions;
22

33
using System.Collections.Generic;
44
using System.Linq;
55
using System.Threading;
66
using System.Threading.Tasks;
7-
using AcceptanceTesting;
8-
using EndpointTemplates;
9-
using Extensibility;
10-
using Features;
117
using Microsoft.Extensions.DependencyInjection;
128
using NServiceBus;
9+
using NServiceBus.AcceptanceTesting;
10+
using NServiceBus.AcceptanceTests.EndpointTemplates;
11+
using NServiceBus.Extensibility;
12+
using NServiceBus.Features;
13+
using NServiceBus.Persistence;
14+
using NServiceBus.Unicast.Subscriptions;
15+
using NServiceBus.Unicast.Subscriptions.MessageDrivenSubscriptions;
1316
using NUnit.Framework;
14-
using Persistence;
15-
using Unicast.Subscriptions;
16-
using Unicast.Subscriptions.MessageDrivenSubscriptions;
1717
using Conventions = AcceptanceTesting.Customization.Conventions;
1818

1919
public class Pub_from_sendonly : NServiceBusAcceptanceTest
@@ -46,7 +46,7 @@ public SendOnlyPublisher()
4646
b.SendOnly();
4747
b.UsePersistence(typeof(HardCodedPersistence));
4848
b.DisableFeature<AutoSubscribe>();
49-
});
49+
}, metadata => metadata.RegisterSelfAsPublisherFor<MyEvent>(this));
5050
}
5151
}
5252

0 commit comments

Comments
 (0)