Accessing IMessageHandlerContext from Behaviour<ITransportReceiveContext>

In implementing Customized Error Handling as outlined in the example provided here: Customizing Error Handling • NServiceBus • Particular Docs

I have a use case where if the failed message is of a specific type, reply to sender. So my invoked task looks similar to what is outlined below:

public override async Task Invoke(ITransportReceiveContext context, Func<Task> next)
     {
          try {
               await next().ConfigureAwait(false);
               Console.WriteLine("Message {0} processed successfully", context.Message.MessageId);
          }
          catch (MessageDeserializationException deserializationException)
          {
               throw deserializationException;
          }
          catch (Exception ex)
          {
          if (context.Message.Headers["NServiceBus.EnclosedMessageTypes"].StartsWith("Namespace.FailedMessageIHaveToReplyAbout"))
               {
                    var command = Deserialize<FailedMessageIHaveToReplyAbout>(context.Message.Body);
                    //reply
               }
               else
               {
                    //don't reply
               }
          }
    
}

Is there anyway to access the imessagehandlercontext or do I have to manually route a message (ie. create an endpoint instance and send a message)? As always, thanks in advance for any guidance you may provide.

Hi Jatinder

The transport receive context that is available in that stage in the pipeline does not allow to send messages. That is prevented by design. You could change your behavior so that it operates in the IIncomingPhysicalMessageContext part of the pipeline. More information available at Steps, Stages and Connectors • NServiceBus • Particular Docs. On the physical context you can use normal message operations.

I would like to suggest though to make a step back first and analyze the requirements a bit more. Why do you need to reply back to the sender. That sounds to me like unnecessary coupling between the receiver of the message and the sender. In many cases, it is because we are trying to mimic a synchronous type of interaction over messaging which is inherently asynchronous and of fire & forget nature. Maybe you can explain a bit more the use case you have that thinks you need to customize the error handling so that we can help you better?

Regards
Daniel

Hi Daniel,

Thanks for you reply. Let me outline the changing requirements we are trying to implement a solution for. I greatly appreciate any feedback you might be able to provide.

Previously we had a Publishing System that would let Subscribers know if content was approved/un-approved and worked in a fire and forget manner. If Subscribers failed in their processing of content changes it was their own business, and of no concern to the Publisher.

Recently there has been a change in the business where the status of content in the Publishing System is only updated once the Publishing System has received confirmation that all Subscribers have successfully updated their systems to reflect content changes first. Furthermore if any Subscriber errors in processing a content change we want the Publishing System notified of that error.

I hope that helps explain the use cases we are trying to adapt around. Please let me know if you require any further clarification. I look forward to your feedback.

Hi Jatinder,

I’m having a hard time with the following requirement:

That goes against the code concept of pub/sub where publishers are decoupled from subscribers. Events notify about something that allready took place. From your description it sounds like you expect other parties to perform some work and get back confirmation (command scenario) rather raising an event.

Hi Sean,

In your opinion then, does the change in requirements call for abandoning pub/sub and and switching to a command implementation? I will say that if this was a green field implementation, I find it less likely we would be implementing this solution via pub/sub.

Hard for me to tell you what should or should not take place as I don’t know all the details.
Thinking out loud, if you set an expection on the receivers of those messages, you’re sending commands. And you expect to have an outcome, meaning that you also know all of the receivers? In pub/sub publisher doesn’t know and doesn’t care about subscribers. Also, it announces something that has happened, which is irreversable. ConentPublished or UserAdded.

With events, there could be many receivers or no receivers at all. As a publisher you are never concerned about it. You could have a follow up message indicating event was processed, but how would you know how many confirmation like that you’re expected to have.

Do you know all of your receivers?

Again, without understanding the details of the scenario, I hesitate to suggest a specific route.

Hi jatinder

Without knowing more it is hard to give advice and I might be prematurely jumping to conclusions. For me it sounds a bit like Sean mentioned that there is no true autonomy between the publisher and subscribers. It sounds like the master is the publisher and the subscribers have a transcational need/envy for the data of the subscriber including more or less strong consistency requirements. This might be an indication that the boundaries between the publisher and the subscribers are incorrect.

What are the subscribers doing with that data? Maybe you can solve this by using a view model approach so that the service owning the data remains the logical owner.

If this is a classical integration problem then maybe a more hub and spoke integration pattern is the key where data is aggregated for the integration purpose over en ETL like process

Long story short it sounds like messaging is not what you want in that specific case because you’ll end up building a highly complex and coupled solution that over time will closely resemble a data replication mechanism and thus undermine all the benefits messaging wad supposed to provide you

Regards

Daniel