Problem with nested transactions

993 views
Skip to first unread message

René M. Andersen

unread,
Dec 23, 2011, 3:41:41 AM12/23/11
to rhino-t...@googlegroups.com

We are working on a .Net application using Rhino Service Bus (2.2.1.0) in transactional mode in order to obtain a persistent queue. We cannot use the transaction created by Rhino Service Bus since this could cause the transaction to be promoted to a distributed transaction, which we do not want. We have therefore chosen to create a transaction with Suppress option ("new TransactionScope(TransactionScopeOption.Suppress)"). This is managed by a MessageModule which starts and stops the transaction in MessageArrived and BeforeCommit event handlers.

Our problem now is, that when an uncatched exception occurs in a consumer, Rhino Service Bus tries to dispose its transaction scope. But we have no handles that we can use to dispose our transaction before Rhino Service Bus disposes its own transaction, and therefore Rhino Service Bus fails with the following message:

 

2011-12-22 15:02:54 [WARN ] - [Rhino.ServiceBus.Msmq.MsmqTransport]: Failed to dispose of transaction in error mode.

System.InvalidOperationException: TransactionScope nested incorrectly.

   at System.Transactions.TransactionScope.Dispose()

   at Rhino.ServiceBus.Transport.MessageHandlingCompletion.DisposeTransactionIfNotAlreadyDisposed(Boolean txDisposed)

 

A solution could of course be to surround all our logic in the consumers with a try-finally block which ends the transaction before the exception reaches Rhino Service Bus. But that will introduce a dependency from all consumers to the message module holding the transaction, which we would like to avoid. A better solution from our perspective would be if Rhino Service Bus had a BeforeRollback/BeforeDispose event (or similar), in which we could close our transaction before Rhino Service Bus closes its transaction. However there does not seem to be this option.

Have you got any other ideas of a solution to this problem?


Best Regards

René

Jason Meckley

unread,
Dec 23, 2011, 8:15:06 AM12/23/11
to rhino-t...@googlegroups.com
use the mesage arrived and message completed events. (not before commit.)

René M. Andersen

unread,
Dec 24, 2011, 2:13:14 AM12/24/11
to rhino-t...@googlegroups.com
We start our inner transaction in the message arrived event handler. It seems that the Rhino Service Bus transaction is disposed before the message completed and message processing failed events are raised, thus causing the "transaction nested incorrectly" exception.

We need to dispose our inner transaction first to avoid exceptions.

Jason Meckley

unread,
Dec 24, 2011, 6:38:34 AM12/24/11
to rhino-t...@googlegroups.com
[threadstatic] private static Transaction tx;

private bool MessageArrived(Information info)
{
   if(tx == null)
   {
         tx = new Transaction(suppress);
   }
   return false;
}

private void MessageProcessingCompleted(Information info, Exception ex)
{
   using(tx)
   {
      if(ex == null)
      {
          tx.Complete();
      }
   }
}

René M. Andersen

unread,
Dec 27, 2011, 3:23:19 AM12/27/11
to rhino-t...@googlegroups.com
Thanks for your input, but the exception remains. The problem lies in the fact that Rhino Service Bus disposes its outer transaction before any message module events are raised. It is the Dispose of the outer transaction that causes the exception because the inner exception has not been yet been disposed.

It all happens in the HandleMessageCompletion method of the MessageHandlingCompletion class in Rhino Service BusThe first thing this method does, If an exception occur, is to dispose the outer transaction. Next it raises the appropriate events (message completed etc.).

This led us to believe that some kind of BeforeDispose/BeforeRollback event is missing. We already have a BeforeMessageTransactionCommit event to handle our transaction in case of success.

René M. Andersen

unread,
Jan 5, 2012, 3:31:17 AM1/5/12
to rhino-t...@googlegroups.com
We still have this problem.

Will a pull request with a new BeforeMessageTransactionDispose event be accepted as a fix for this scenario?

regards
René

Jason Meckley

unread,
Jan 5, 2012, 8:04:19 AM1/5/12
to rhino-t...@googlegroups.com
can you post the relevant code, or spike an example on github or your current problem. I still believe what you require can be done within the current version.

Corey Kaylor

unread,
Jan 5, 2012, 8:37:51 AM1/5/12
to rhino-t...@googlegroups.com
I agree with Jason. We can take a pull request if it comes down to it though. These types of issues would be much better dealt with in my v3 suggested changes.

On Thu, Jan 5, 2012 at 6:04 AM, Jason Meckley <jasonm...@gmail.com> wrote:
can you post the relevant code, or spike an example on github or your current problem. I still believe what you require can be done within the current version.

--
You received this message because you are subscribed to the Google Groups "Rhino Tools Dev" group.
To view this discussion on the web visit https://groups.google.com/d/msg/rhino-tools-dev/-/Jf_G7b57jRsJ.

To post to this group, send email to rhino-t...@googlegroups.com.
To unsubscribe from this group, send email to rhino-tools-d...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rhino-tools-dev?hl=en.

René M. Andersen

unread,
Jan 6, 2012, 6:58:17 AM1/6/12
to rhino-t...@googlegroups.com
I have forked the Rhino Service Bus repository to:

and added a unit test that reproduces our scenario:

A few things to note about the test:
1. 
I attempt to dispose the nested transaction in several event handlers in my test message module simply to illustrate that none of them are called before the outer transaction is disposed and thus causing the exception.

2.
I verify the error by looking in the log4net output simply because the transaction exception is caught by the Rhino Service Bus code and simply logged (in the MessageHandlingCompletion class). So this is the only way I could think of to verify if the exception occured.
The exception itself can also be seen in the console output of the test (since I configure log4net).

Let me know if you can see a way around this. If not I can implement a fix and send you guys a pull request.

Regards
René

Corey Kaylor

unread,
Jan 11, 2012, 12:18:50 PM1/11/12
to rhino-t...@googlegroups.com
Send a pull request for the changes you want and I'll get them in.


Regards
René

--
You received this message because you are subscribed to the Google Groups "Rhino Tools Dev" group.
To view this discussion on the web visit https://groups.google.com/d/msg/rhino-tools-dev/-/jA1VZXWlxSYJ.
Reply all
Reply to author
Forward
0 new messages