Migrating timeouts from NH TimeoutManager to SQS

NServiceBus Version: 7.x

We are in the process of migrating our codebase over from MSMQ to the SQS Transport (latest versions of both). Is there any guidance, documentation or existing scripts for migrating timeouts out of the TimeoutManager NHIbernate persistence table into the SQS delay queues? We have a number of sagas that defer timeouts for many days, in some cases months, and it is not practical to run the MSMQ transport in parallel in order to somehow drain the existing timeouts. Any guidance would be appreciated.

Hi Joe

Unfortunately we don’t have guidance for switching timeouts from NHibernate persistence to SQLS delay queues. This sample here shows how to migrate from NHibernate persistence to SQL Transport native timeouts

The scripts there might give you a starting point. I would use those scripts to fetch all the timeouts and then essentially defer all the found timeouts in NHibernate Persistence and then use a dedicated send-only endpoint to defer the appropriate message into the future

var sendOptions = new SendOptions();
sendOptions.DelayDeliveryWith(TimeSpan.FromMinutes(30));
await endpoint.Send(new MessageToBeSentLater(), sendOptions)
    .ConfigureAwait(false);

Regards
Daniel

Hi Daniel, thanks for the starting point.

High level I was thinking write a script/cli that reads from TimeoutEntity table and adds whatever headers I need and sends the raw message to the delay queue (similar to https://docs.particular.net/transports/sqs/operations-scripting#native-send-the-native-send-helper-methods)

The sql scripts you have here might help me move data to a staging table, and add the headers I need

I assume I need this one https://github.com/Particular/NServiceBus.AmazonSQS/blob/4fa42879160c269ac8547b8c93ce6f46c2f8ce1b/src/NServiceBus.AmazonSQS/TransportHeaders.cs#L7

Where can I find the other headers I need?

This repo also contains a branch to move timeouts to a transport but then from RavenDB to RabbitMQ. The process is pretty similar. Read from storage and then defer the messages on the transport.

You can see how it deals with headers here:

The good thing about using a send-only endpoint or NServiceBus.Raw (as pointed out by the comment of @ramonsmits) is that you don’t have to deal with the delayed headers really. Because you are going through the AmazonSQS transport dispatcher (transport level infrastructure thing that sends messages) all the appropriate headers and attributes for delaying messages are set automatically. Your responsibility is then only to make sure the payload and the “regular” message headers are set accordingly.

Does that help @jfeinour?

Using the raw Transport makes sense. I was wondering how the send only would’ve dealt with the raw body. I can piece together the rest from here. Thanks @danielmarbach @ramonsmits!

Even if you are not using NSB Raw you can get access to the IDispatchMessages interface for example in a feature startup task. You basically create a feature, add a startup task and declare a dependency to IDispatchMessages in the constructor.