1
votes

I have updated to NServiceBus 6, where the IProvideConfiguration<UnicastBusConfig> and its MessageEndpointMappings are obsolete.

I have followed the publish/subscribe instructions in the documentation. As I understand it, it is now required to explicitly name the publishing endpoints when subscribing to an event.

Before, I could specific the event interface, the endpoint would be the name of the subscriber:

config.MessageEndpointMappings.Add(
                new MessageEndpointMapping
                {
                    AssemblyName = MyAssemblyName,
                    TypeFullName = typeof( IMyEvent ) ),
                    Endpoint = "SubscribingEndpoint"
                } );

Now: this goes away and I have the following. This entirely replaces the need for an IProvideConfiguration class:

    var routing = endpointConfiguration.UseTransport<MsmqTransport>().Routing();
    endpointConfiguration.SendFailedMessagesTo( "error" );
    endpointConfiguration.AuditProcessedMessagesTo( "audit" );
    //register command
    routing.RouteToEndpoint( typeof( MyCommand), "SomeEndpoint" );
    //subscribe to event
    routing.RegisterPublisher(typeof(IMyEvent), "PublishingEndpoint" ); //?

So here I would have to specify the publisher of the IMyEvent, not the subscriber. In NSB5, this was not necessary.

So what do I do if the event is published by several endpoints?

1
An event was always only published from one endpoint (following the rule there is only one publisher...) and AFAIK it was always the case you needed to provide the publisher address for the event... What are you trying to do?Sean Farmar
@SeanFarmar I understand that an event should only be published by one endpoint. In NSB5 I a subscriber would subscribe as I have shown above, by using its own endpoint name in the MessageEndpointMapping, and not the publisher's endpoint name. The v5 documentation says as much. This is more of a configuration issue question than an event VS command question. Sending a command would work in this case, except that it's more work to setup the routing for it.John
I'm confused, can you provide the link stating that you can use the endpoint's name and not the publisher's endpoint name? AFAIK it was always the case (and it makes sense) that the subscriber will send a subscription message to the publisher, so it will need the publisher's endpoint name in configuration...Sean Farmar

1 Answers

1
votes

To answer your question:

So what do I do if the event is published by several endpoints?

You can subscribe to the same event from multiple publishers by having multiple RegisterPublisher calls from your subscriber.

Note that it's usually considered a smell if the same event is publishes from multiple logical endpoints. You might want to consider using different event types for each logical endpoint or maybe switch from an event to a command. If you're not sure about the message design, it's highly recommended to visit the Particular Software Google Group, people are very happy to help you with design questions which extend this SO question.

Regarding the change between V5 and V6:

In NSB5 I a subscriber would subscribe as I have shown above, by using its own endpoint name in the MessageEndpointMapping, and not the publisher's endpoint name.

I'm having a hard time following this statement. V5 and V6 use the same approach to subscribing, just a different syntax.

Since you're using MSMQ, a subscriber has to send a subscription message to each publisher of an event. For the subscriber to know where to send the subscription message, it needs routing information for this. This is where V5 and V6 use a different syntax:

  • V5 will look for a matching route in it's MessageEndpointMappings. It will send the subscription message to the endpoint specified in the mappings (which would be SubscribingEndpoint in your sample code).
  • V6 enforces separation between subscription messages and commands. That's why there are different APIs for routing regular commands and for routing subscription messages. Broker based transports (e.g. RabbitMQ) don't need subscription messages and therefore no routing for subscription messages is needed while every transport still requires routing information to send commands.

As you see, there is only a difference in syntax between V5 and V6, there should be no change in concepts. Since you claim that the above example works for you, I can only imagine a few reasons why that is so:

  • Your logical endpoints share the same subscription storage, which might cause the subscription message sent to the subscriber endpoint to be visible to the publisher by accident.
  • Your persistent subscription storage used by the publisher already contains a subscription from the subscriber. Although it might no longer receive subscription messages (because with your configuration it shouldn't) it still has an "old" subscription which is used by the publisher.

Whether one of these reasons might explain the behavior your seeing or not, when using MSMQ transport with NServiceBus, a subscriber always needs to have a route configured to the publisher in order for the subscription message to reach the publisher. This design didn't change between V5 and V6.

There is a nice sample demonstrating Publish/Subscribe in both V5 and V6 available on the Particular docs: https://docs.particular.net/samples/pubsub/?version=core_5

I have updated to NServiceBus 6, where the IProvideConfiguration and its MessageEndpointMappings are obsolete.

Please note, that in V6, both these APIs are obsoleted with a warning, but they still continue to work. These APIs will be removed in the next major version.

I hope this clears things up a bit.