I am using NServiceBus (latest) with SQL Server everything…
I have what I believe to be a reasonably simple question - though my process or understanding may be a bit off kilter, so some suggestions are welcome.
What I would like to achieve is for a failed handler to publish an event prior to the message being sent to the message queue. I had this in a try/catch inside the handler where I was using the current context to publish the event and then re-throw the exception, but obviously then the published event gets rolled back, so the failure is never noticed. And I would also get an event per retry which isn’t ideal either.
Does the answer lie in a behaviour? Is there some other way to have an event published prior to a message heading to the error queue?
var endpointConfiguration = new EndpointConfiguration("MyEndpoint");
endpointConfiguration.UseTransport<LearningTransport>();
IMessageSession messageSession = null;
endpointConfiguration.Recoverability().Delayed(s => s.NumberOfRetries(0));
endpointConfiguration.Recoverability()
.Failed(s => s.OnMessageSentToErrorQueue(fm =>
{
var options = new SendOptions();
options.RequiredImmediateDispatch();//to make sure the send operation doesn't participate in the receive transaction
options.SetDestination("SomeOtherEndpoint");
return messageSession.Send(new ReportThatMessageFailed
{
Reason = fm.Exception.Message
}, options);
}));
messageSession = await Endpoint.Start(endpointConfiguration)
.ConfigureAwait(false);
Note the call to RequiredImmediateDispatch to make sure that the operation doesn’t enlist in the current receive transaction to make sure that it gets sent our no matter what.
Depending on the business requirements potentially use a saga to control the retry behaviour and report various statuses back to other endpoints. See Sagas • NServiceBus • Particular Docs
Can you share some more details on why you need to report that the message was moved to the error queue to other endpoints?
Thanks for the quick reply Andreas. I think option 1. is exactly what I’m looking for.
A bit of background - we’ve been using NServiceBus for a good few years on MSMQ, but we are moving forward with .Net Core now and there are a few migration issues that we are facing. This has driven us to use SQL transport and native .Net Core DI.
The migration is a step at a time and the current functionality that I am replacing is to post to MS Teams on failure (this was before Service Pulse etc. became more affordable for a small project like ours). We have an endpoint subscribed to that event that will do this.
Ultimately we will look to taking advantage of Service Control etc, but for the time being I think option 1 will suffice.
Hi Sean, based on the description of your use case I would recommend you to go for option 2. That allows you to deploy a single endpoint that listens to all failed messages from all endpoints and handle them (send the message to teams), instead of replicating this logic in every endpoint you deploy.
Just my 2 cents…
Thanks for the input and I certainly agree with you there. At the moment we are dynamically loading an assemby per endpoint and the endpoints inherit from a base class where this is done. So from a dev point of view the logic is in a single place - though does get deployed multiple times.
I will soon have the time to start looking at the ServiceControl offering and other options now available to us and can then remove that code if/when we get that set up.