Transactions & Message Processing
As a part of the NServiceBus "Fault-Tolerant by Default" design
transactions are managed automatically be the infrastructure
so that developers don't have to remember the configuration
of all threading and state management elements.
Clients and Servers
While it is desirable for server code to process messages transactionally,
it often isn't required for clients, particularly desktop applications.
This is one of the differences between the AsA_Client and AsA_Server settings of the
generic host in NServiceBus.
Specifying transactions in code
If you aren't using the generic host, you can specify whether the current endpoint should process
messages transactionally or not by setting the ".IsTransactional(true)" after ".MsmqTransport()"
If you want to override the System.Transactions default timeout of 10 minutes,
follow the steps described in this blog post.
Distributed Transaction Coordinator
On Windows, there is an OS-level service called the DTC which manages transactions that
need to span multiple resources - like queues and databases. This service isn't always
configured correctly and may require some trouble-shooting.
First of all, you'll need to download a tool called
DTCPing. This tool will help you find out if one machine is able to access a
remote machine over the DTC. Here's what that tool looks like:

If you get an error referring to the RPC Endpoint Mapper, go to the command
prompt and run "dcomcnfg". After you start dcomcnfg you should see the Component
Services screen below.
From here, what needs to be done is open some ports. To do this, right-click "My
Computer" and go to the "Default Protocols" tab. From there, select
"Connection-oriented TCP/IP" and click the "Properties" button. In the
"Properties for COM Internet Services" dialog that opens, check that the Port
Ranges includes "5000-6000" as shown in the following image:

If the list of Port Ranges is empty, click the "Add..." button and enter
"5000-6000" in the dialog box that opens up. After doing so, your screen should
look like the image above. You can probably make do with less than 1000 open
ports, but it depends on the number of machines you are looking to connect to
each other over the DTC.
After clicking OK and returning to the Component Services screen, navigate to
the "Local DTC" node under the Distributed Transaction Coordinator folder, right
click, and select "Properties". In the dialog that opens, select the Security
tab as shown below:

Ensure that the properties you see are the same as the above.
After finishing all the steps above, restart the computer.
If DTCPing isn't working after all of the above, check that the needed ports are
open in the firewall. Consider removing the DTC exceptions in the firewall and
add them again to make sure.
If DTCPing gives you a message about finding the name but not reaching it, the
first thing to do is a simple ping by running “ping computer_name” in the
command prompt. If you discover that the machine cannot be reached by ping, it
could be that you have a DNS problem that may require your Network
Administrator's help.
Make sure you perform all of the above steps not just on the servers that
connect to the database, but also on the database servers as well.
Finally, check the TCP ports in use on the servers making sure that each has a
different port configured as the communication is bi-directional. At this point,
you should be able to run transactional NServiceBus endpoints.
Content in this section derived from Mikael Henriksson's
blog.
The Message Processing Loop
Messages are processed in NServiceBus as follows:
- The queue is peeked to see if there's a message.
- If so, a distributed transaction is started.
-
The queue is contacted again to receive a message.
This is because multiple threads may have peeked the same message.
The queue makes sure only one thread will actually get a given message.
-
If the thread is able to get it, NServiceBus tries to deserialize
the message. If this fails, the message is moved to the configured error queue
and the transaction commits.
-
After a successful deserialization, NServiceBus invokes all infrastructure
and applicative message modules and handlers. An exception in this step will
cause the transaction to rollback and the message to return to the input queue.
- This will happen the "MaxRetries" configurable number of times
- After that, the message will be moved to the configured error queue
In this manner, even under all kinds of failure conditions like the application
server restarting in the middle of a message, or a database deadlock, messages are
not lost.
In the common case, the automatic retry mechanism is able to recover from most
temporary problems. When that isn't possible, the message ends up in the error queue.
Resolving More Permanent Errors
There are multiple situations in which more permanent errors affect systems. Despite
their diversity, the NServiceBus solution is the same. Before describing it, let's
drill into some of these situations.
- The database is down
- An external or internal web service is down
- The system was upgraded accidentally breaking backwards-compatibility
In all of the above, administrative action is needed - from things as simple as
bringing up a database or web service again, to more complex actions like reverting
to the previous version of the system.
What we see here is that there's nothing necessarily wrong with the message itself.
It might contain valuable information that shouldn't get lost under these conditions.
Therefore, after the administrator finishes resolving the issue, they should return
the message to the queue it came from. Luckily, NServiceBus comes with a tool that
does exactly that.
ReturnToSourceQueue.exe

You can find this tool in the "Tools" directory found in your NServiceBus download.
Administrators provide the name of the error queue they'd like to use, and either specify
a specific message ID to return to its source queue, or 'all' to return all messages
in the given error queue, each to its respective source queue.