This post delves into the details of a feature I contributed to Rhino.ServiceBus, available in the recently released version 3.0. Previously, you were able to add custom headers to outgoing messages by registering an implementation of ICustomizeMessageHeaders with the container. That interface has been renamed to ICustomizeOutgoingMessages, and now allows you to also set a DeliverBy and/or MaxAttempts. You can register any number of implementations with the container, and the bus will invoke each one as it builds outgoing messages.
Rhino.Queues has full support for DeliverBy and MaxAttempts. If either of these two options is set, the message will be moved to the OutgoingHistory and marked as failed transmission if the message couldn’t be delivered in time.
MSMQ supports DeliverBy by setting the TimeToReachQueue property on the MSMQ message. MaxAttempts is only supported when set to 1, which sets TimeToReachQueue to TimeSpan.Zero, meaning MSMQ only makes one attempt to deliver the message. If MaxAttempts is set to a value other than 1, an InvalidUsageException is thrown.
Because it’s up to the user to create an implementation of ICustomizeOutgoingMessages, the user can set delivery options in a way that works best for them, whether it’s by setting options for specific message types, specific destinations, or reflecting over messages to look for specific attributes or interfaces.
If you want to limit how many times the bus tries delivering messages to endpoints that aren’t always online, you could add a query parameter to the endpoint and the customize using the Destination on the OutgoingMessageInformation.
Maybe you have a message that’s only useful for a short period of time.
Using the OutgoingMessageInformation instance, you can inspect the Messages being sent, the Destination endpoint, and the Source endpoint to make any customizations you need. You can modify the Headers collection on that instance, set MaxAttempts, or set DeliverBy.