Tuesday, 3 November 2015

NServiceBus and MSMQ Transport Transactions

If Distributed Transactions and ambient transactions are turned off, then you are reliant upon MSMQ transactions.
On a transactional queue and with the appropriate code then the Receive operation on the queue will be transactional. This allows NSB to take a message off a queue - preventing other handlers from reading it - process it and if it fails put it back on the queue.
However the MSMQ transaction will only group Receives together in a transaction, or Sends, not a mixture.
So if you have code like this:

a. Begin MSMQ transaction
b. Read Message
c. Process Message
d. Send Result Message onwards
e. Commit Transaction

then this is fine if the point D is the last action in the transaction. If anything fails before it, the MSMQ transaction will fail and the original message at B will be put on the input queue. No output message will have been sent as the processing before it will have failed.

However if you have more than one output message it will yield bad results. Take this scenario:

a. Begin MSMQ transaction
b. Read Message
c. Process some of the message
d. Send Intermediary Message onwards
e. Process some more
f. Send Result Message onwards
g. Commit Transaction

If step E fails then the transaction will be rolled back and the message at B returned to the input queue. However the MSMQ transaction will not roll back step D - the intermediary message will be sent despite the failure of the transaction.

No comments:

Post a comment