Conditionally forward message to different broker w/ same transport

Hello,

Due to our broker topology (mirrored instances of RMQ) I would like to add a behavior to our pipeline that checks a condition and forwards or handles the Event based on that condition.

I’ve reviewed the Router and the Gateway but they seem to have static routing and are perhaps overkill for what I’m trying to achieve.

The other option I’ve considered is publishing the Event to both brokers at the originating endpoint and either discard or handle but this Event initiates a (stateless) workflow where this condition could change at any point within the workflow.

Is there a better way to achieve this?

Hi Jeremy,

Option A
Publishing the event to both is definitely an option, unless there’s a large amount of traffic and another option should be chosen. I have a sample set up for this which you can find here: https://github.com/dvdstelt/priority-queues

The thing is, you’re not clear on the “condition” that you mention. Theoretically we don’t recommend content-based-routing. We recommend a sender is not aware of different receivers and when it should select on or the other to send a message.

If there is a large amount of traffic and you don’t want every message to end up at two endpoints because of performance (I/O) issues, there are other options.

Option B
One thing is to have the sender side select where the message should go. Which couples that sender to the receivers in that it has too much knowledge.

Option C
Another option is that the receiving side has a very small component where it knows about itself and its own receivers. That component is a library that you can deploy anywhere. You could even deploy it on the sender side. Using some sort of interface and scanning assemblies using reflection, the sender could verify which implementations for that interface there are. And instead of actually sending messages to 2 (or more) locations, call out to the implementations. It’s the exact same thing as the priority queues example, except the selection happens before the actual message sending happens.

This might sound exactly like option A, but the difference here is that you can modify the sending of messages, without modifying the sender. It’s just re-deploying the small component(s) and it works. So the responsibility (and code) is still with the team that actually processes that messages, but deployment looks a little bit different.

Thanks for the reply Dennis. The condition is an external data point (not part of the message itself), essentially a switch, that determines whether to use Broker instance 1 or instance 2. This condition is checked at the time of origination to determine where to start the workflow but could change at any step.

Option A
This doesn’t seem to account for the condition to change in the middle of a workflow. I’d like to forward the event to the other broker at any step. In your sample, we would have the same endpoints configured for each server.

Option B
The originating endpoint is currently selecting which broker/endpoint to use to publish the Event but the receivers are in-turn publishing their own events. I suppose I could put the condition check in every Handler but even then (AFAIK) handlers themselves are bound to a single transport (or broker in our case).

Option C
Unfortunately it is a requirement to be able to transfer the message to a separate broker and subsequent host rather than choose an implementation within the same host.

I suppose another option would be to use the native RMQ client within a behavior?

Looking what you’ve provided so far about your scenario, I don’t think you’ll be able to solve this with just standard NServiceBus endpoints.

It sounds like you’ve got two completely separate RabbitMQ broker instances that aren’t connected in any way, is that correct?

If so, then there isn’t going to be a way to have one endpoint communicate to both brokers. You need separate endpoints, one for each broker.

At that point, you do need some sort of bridging tech to get messages from one broker over to another broker.

We do have the Gateway that could be used for that, and there are community options like the Router package as well.

Another potential option would be to handle it inside the broker itself through things like federated exchanges and the shovel plugin. That way the individual endpoints would have no special knowledge of what’s going on, and would instead just send messages as normal. When the message arrives at the shovel queue, for example, it would get sent over to the other broker.