1

Is there a way to send a message to NServiceBus when, and only when, all the retries performed by Recoverability has failed? In short, I want to send a new message to another queue (at the same time it gets sent to the error queue). I not sure if, or how, I can plug into the pipeline to do this.

I have a behavior below that when I throw a specific exception, it handles it by sending an event to NServiceBus (bypassing retries), but I have another use case where I want to send that same event only after retries have failed as well.

class OperationFailedExceptionBehavior : Behavior<IIncomingLogicalMessageContext>
{
    public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
    {
        try
        {
            await next().ConfigureAwait(false);
        }
        catch (OperationFailedException ex)
        {
            //since we're catching the exception, retries will no longer occur.
            await context.Publish(new OperationFailedEvent(ex));
        }
    }
}
Nathan A
  • 11,059
  • 4
  • 47
  • 63

1 Answers1

2

Probably Notifications are what you're looking for. You can subscribe to error notifications, that I think will give you all the details you need to implement the mentioned requirement.

For more details: https://docs.particular.net/nservicebus/recoverability/subscribing-to-error-notifications

Mauro Servienti
  • 508
  • 2
  • 8
  • I looked into that possibility, but the event arguments don't pass in any context that then allows me to send another message. My example code gets a IIncomingLogicalMessageContext, which I can then call Publish on. I don't get that (or any other context) argument on the MessageSentToErrorQueue event handler. – Nathan A Aug 24 '18 at 14:46
  • Right. The number of delayed retries is stored in a header `Headers.DelayedRetries`, the number of immediate retries should be stored in the `ImmediateRetries` header. But I'm not sure about this last one. – Mauro Servienti Aug 24 '18 at 15:03
  • Let me ask a clarification: are you interested in moving the failing message to the error queue? Because if that's the case then when a message is failing (even if it's the last failure) the incoming message transaction is always rolled back and any outgoing message won't be sent. You could use the `IMessageSession` interface from the notifications handler and the message will be sent immediately. – Mauro Servienti Aug 24 '18 at 15:12
  • I'm not trying to change the error queue behavior at all. I want it to still end up in the error queue. I'm trying to add an extra publish command to the pipeline when the original Command fails (after retries). For example, if retries fail and the overall command fails, I want to send a new event to a new queue that will result in a message being sent to the user of the failure. Right now, when the message goes to the error queue, there is no way to notify the requesting user of the failure (via NServiceBus). – Nathan A Aug 24 '18 at 15:27
  • 1
    Perfect. Notifications are what you're looking for. In order to send/publish a message while handling a notification just use the `IMessageSession` interface. When sending an additional message when the incoming one fails you don't want to use the message context because you don't want to participate in the incoming message transaction. – Mauro Servienti Aug 24 '18 at 15:30
  • Could you provide a code snippet of that? I'm not sure where I'd get a handle for IMessageSession when that delegate looks like Errors_MessageSentToErrorQueue(object sender, FailedMessage e). – Nathan A Aug 24 '18 at 15:35
  • Nevermind, that comes from IEndpointInstance. Failed to see that. Thanks for the help. – Nathan A Aug 24 '18 at 15:39
  • I was in the process of creating a gist. Good you succeeded. Something similar to the following: https://gist.github.com/mauroservienti/bc336b1cb9983d7bfe2150c2347a3560 – Mauro Servienti Aug 24 '18 at 15:40