1

I am looking into using nservicebus and wondering how hard it would be to do the following in the publish/subscribe topology.

For example, a client(s) would subscribe to User type messages. But only subscribe to a subset of these messages, for example User messages with userkeys of 111,222,xxx,etc.

These subset of keys would also change periodically.

I am having a hard time figuring out if NServiceBus already has a paradigm in place to handle this?

Jason Smith
  • 373
  • 2
  • 6
  • 20

2 Answers2

4

No. This is called "Content-Based Routing", and it's not something that NServiceBus supports. Although NSB supports some broker-based transports (e.g. SQL Server, RabbitMQ), it is logically designed to be a distributed model. In order to do Content-Based routing, there needs to be a central hub that controls the delivery of messages based on content.

Udi Dahan has a post explaining why NSB doesn't support this feature here.

Phil Sandler
  • 27,544
  • 21
  • 86
  • 147
2

The way to approach this is to think about what material differences there are in a User message where the user key is 111 or 222, and a User message where this is not the case.

The likely conclusion is that they do, in fact, represent different things in your business process, as one will be consumed with different effect than the other. This is a signal that you actually need to create new message types to differentiate between these differing business cases.

Let's say for example you have the following event message:

public interface IUserAddedInformation
{
    Guid UserKey { get; set; }
    InformationType informationType { get; set; }
}

public enum InformationType 
{
    Address,
    CreditCard
}

You set up a subscriber to handle the message and process the changes. However, you soon realize that personal data like address and payment data like credit card details are very different, so you want to handle the two instances separately. But how to do this without routing based on the informationType field in the message?

public interface IUserAddedCreditCard
{
    Guid UserKey { get; set; }
}

public interface IUserAddedAddress
{
    Guid UserKey { get; set; }
}

Now you can create separate handlers for both events. Maybe you would be able to go through a similar process to the above example to work out how to get the routing behavior you need.

tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • 1
    +1 and I agree that this is usually the answer. However, there are certainly cases where something equivalent to content-based-routing is needed, and having separate message types isn't possible. For example, imagine an endpoint that publishes market price updates for many thousands of ticker symbols. A specific client is only interested in 10 symbols. It would be very inefficient to receive all events and discard 99.9% of them. – Phil Sandler Mar 12 '15 at 20:12
  • 1
    @PhilSandler yes I completely agree with that. However in that case I would argue that a subscriber should do the "routing" on their end by simply inspecting the messages as they're handled, and discarding any which they are not interested in, although this appears quite wasteful. – tom redfern Mar 12 '15 at 20:59