1
votes

I have one service (service1) which read data from external database. Transforms it and sending to the queue.

Second service (service2) handles message and process it. When processing failed exception is thrown and NServiceBus retrying 5 times to handle it (normal behavior) but reply is never send. :(

All services works in transactions.

My question is: How to send reply (or just send different message back) from handler to service1 when exception is thrown?

I want just notify service1 that processing failed on service2.

Edit 1: For more specific service1 marks reeded records in external database. It is required for further reading other data.

I want to return response from service2 to service1 which unmark records for those where exception was thrown.

Next iteration of reading data from external database may take this records again.

3

3 Answers

5
votes

You can always wrap the Bus.Reply instead of it's own TransactionScope, e.g:

using (var scope = new TransactionScope(TransactionScopeOptions.RequiresNew))
{
    Bus.Reply(your message here)
    scope.Complete();
}

This separates the transaction that you're performing as a result of the error from the transaction that caused the error.

0
votes

The reason Bus.Reply() never makes is that it is part of the same transaction. One option is to have something look at the error queue and push a message back to the originator.

The other option is to tap into the FailedMessageProcessing event in the transport. The downside to this is that you won't know what is failing, just that something is failing. It will also report for each retry which may not be desirable.

It may be the case that you really want synchronous request/response and therefore NSB may not be what you need at all. If you give us some more detail around the business case we may be able to provide more suggestions.

0
votes

just as enhancement to Jonathan Oliver, surround the using statement with finally block after your try-catch block to be like this

            finally
            {
                using (var scope = new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    Bus.Reply<MyResponseObject>(reply);
                    scope.Complete();
                }
            }