On an initial load of 60000+ files our nServiceBus handler threw an exception
NServiceBus.Unicast.Queuing.FailedToSendMessageException: Failed to send message to address: queue@machine —> System.Messaging.MessageQueueException: Cannot enlist the transaction.
Repro
No repro – no issue. Sleeping for 61 seconds caused the same exception. Complete solution for download at the end of the post.
public void Handle(DoSomethingCommand message) { // wait for the timeout of 1 minute log.InfoFormat("Sleeping"); Thread.Sleep(61000); // throws System.Messaging.MessageQueueException: Bus.Send<DoAnotherThingCommand>(m => { }); }
Investigation
Looks like a transaction timeout. This is what the MSDTC Transaction Statistics look like
Every transaction is aborted.
Solution
Setting the transaction timeout for MSDTC did not solve this issue. The timeout of 0 (never timeout) still gave the exception. But thanks to Teun we’ve solved it.
Overwriting the transaction timeout in the config did the trick.
<system.transactions> <defaultSettings timeout="00:05:00"/> </system.transactions>
Now the transactions succeed and the DoAnotherThingCommands are send and processed.
References
- Link to blog of Teun
- Complete repro code
Pingback: DTC troubles with long running transactions in NServiceBus
Thanks for posting! This saved me a bunch of time.
Alternative solution (better?): Create a new TransactionScope with TransactionScope.Suppress as long as all files are loaded before the Bus.Send. See http://stackoverflow.com/questions/13386745/recursive-bus-send-with-in-a-handler-transactions-threading-tasks
This way you can remove transaction scope on individual handlers or part of handlers. Downloading a large file from the internet, then Bus.Send(HandleDownloadedFileCommand) is an example usage.
Thanks for sharing this Trygve!