How do I stop NServiceBus by rerunning a message that does NOT throw an exception?

I am experiencing trying behavior that I cannot find a link to the documentation or search terms I have tried. Basically, if a handler takes more than 60 seconds to process a message (note that it does NOT throw an exception), NServiceBus will launch another handler to process the same message. This means that the work done by the handler is done (at least) twice (often 5 times since I have MaxRetries set to 5).

I want the message to be re-checked if it actually fails (i.e. an exception is thrown), not just because it takes more than a minute.

Is this behavior constructed? Can it be turned off? Is "60 seconds" configurable?

In the logs, it just looks like a processed new message:

2014-12-09 14:50:38,406 [13] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - ChildContainerBehavior
2014-12-09 14:50:38,422 [13] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - MessageHandlingLoggingBehavior
2014-12-09 14:50:38,430 [13] DEBUG NServiceBus.Unicast.Behaviors.MessageHandlingLoggingBehavior - Received message with ID 031e6070-4397-4e55-8670-a3fc00f49d7c from sender Foo
2014-12-09 14:50:38,440 [13] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - ImpersonateSenderBehavior
...
2014-12-09 14:50:40,313 [13] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - InvokeHandlersBehavior
2014-12-09 14:50:40,319 [13] INFO  MyHandler - Running
...
...
2014-12-09 14:51:38,642 [15] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - ChildContainerBehavior
2014-12-09 14:51:38,667 [15] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - MessageHandlingLoggingBehavior
2014-12-09 14:51:38,678 [15] DEBUG NServiceBus.Unicast.Behaviors.MessageHandlingLoggingBehavior - Received message with ID 031e6070-4397-4e55-8670-a3fc00f49d7c from sender Foo
2014-12-09 14:51:38,686 [15] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - ImpersonateSenderBehavior
...
2014-12-09 14:51:38,831 [15] DEBUG NServiceBus.Pipeline.BehaviorChain`1 - InvokeHandlersBehavior
2014-12-09 14:51:38,837 [15] INFO  MyHandler - Running

      

+3


source to share


3 answers


Mauro was on the right track, but the magazines didn't show him very well. We are using SQL Server for message queues. Transactions by default expire after 60 seconds, but the timeout does not throw any errors. Only when message processing finishes, NServiceBus will try to update / move the completed message, but this is not possible because the transaction is no longer valid (an exception is then thrown).

The reason the second handler only starts running after 60 seconds is because concurrency is enabled, and as soon as the transaction ends for the first handler, the message is effectively made available to another thread that needs to be picked up (it was blocked up to that point).

So the solution is to add something like this to the config:



  <system.transactions>
    <defaultSettings timeout="00:10:00" />
  </system.transactions>

      

(Presumably if you are using MSMQ as your message transport a different timeout might apply ...)

+1


source


I had the same symptoms and the problem was long running transactions via DTC (Distributed Transactions).

As Mauro suggests, DTC has a default timeout of 60 seconds. This can be changed either on the system:

Start Component Services, then expand Component Services → Computers → My Computer and right-click and select Properties. In the "Options" tab, you can set the desired default timeout.

Alternatively, you can change it using app.config :

<configuration>
  <system.transactions>
    <defaultSettings timeout="00:10:00"/>
  </system.transactions>
</configuration>

      

However, there is a caveat here. The system default is still set to 10 minutes! If you know that you will have transactions longer than 10 minutes, you need to add the following to machine.config :

<configuration>
  <system.transactions>
    <machineSettings maxTimeout="01:00:00" />
  </system.transactions>
</configuration>

      



Machine.config is in

%windir%\Microsoft.NET\Framework64\[version]\config\machine.config

      

Literature:

DTC issues with long term transactions in NServiceBus

Override default System.Transactions timeout 10 minutes in code

Where is my machine.config file?

+1


source


For those who just don't want NServiceBus to mess with transactional stuff (aka), one can simply force NSB to stop managing handlers in the transaction scope:

//e.g. When using the BusConfiguration object:
 config.Transactions()
     .DoNotWrapHandlersExecutionInATransactionScope();

      

0


source







All Articles