Delay command via saga

Is it a common and recommended design, to let the starting Saga message contain another message that should be sent when completed? (the message will be stored in the Saga data)

I have a message handler that in most scenarios could handle a command A (data should be stored in a local DB)

But sometimes (rarely) it needs to call a web service for additional data, before saving to the DB. But the web service might not have the data ready, so instead I am starting a Saga using Timeouts/Request/Response to query the web service (another handler does this)

When the additional data is ready the Saga will complete and resend the command A, and now I am back in the initial handler, which can perform the DB save.

I end up with this pattern all the time, when receiving a command, that needs some data to be processed first. The saga is necessary since the data might not be ready when calling the web service. I find it a little odd.

Is it a common and recommended design, to let the starting Saga message contain another message that should be sent when completed? (the message will be stored in the Saga data)

You can store the message in the Saga, but it has risks. Depending on the Persistence you could have space issues. For example, with Azure Table Storage you can only store 64KiB in a property(=column) which you could hit when the message is big.

To solve this, you could store the important bits of the message as separate fields in your saga, instead of the whole message. But this will only work if the message doesn’t have a lot of data.

I have a message handler that in most scenarios could handle a command A (data should be stored in a local DB)

But sometimes (rarely) it needs to call a web service for additional data, before saving to the DB. But the web service might not have the data ready, so instead I am starting a Saga using Timeouts/Request/Response to query the web service (another handler does this)

I wouldn’t solve your problem in this way because you’re creating a saga for all the messages, while you only rarely need it.

I would separate this into two pieces: storing and enriching.

The default handler (no saga) StoreDataMessageHandler checks if additional data is needed. If not, it will store the data. If it needs additional data, it will send a new message EnrichData.

Then you can choice to have a Saga handeling this message (and have a Request-Reply to the web service). When the reply is received you can enrich the data and (re)send the enrich message again to the first handler StoreDataMessageHandler.

But better is to have no Saga, but just have a Handler that calls the web service and enriches the message and sends it again. This way you removed the saga completely.

Thanks for the response.

I wasn’t very clear, but indeed the first handler completes without the Saga if all data is ready. It even calls the web service a single time.

But the Saga is needed, if the web service only has the data ready later the same day, right?

OK that is a risk, I haven’t seen this in the documentation? We are using SQL Server.

But the Saga is needed, if the web service only has the data ready later the same day, right?

Normal you would timeouts in a Saga for this because its makes it easier to act when you don’t get a reply and handle this gracefully.

You can also do delay delivery on your own messages. See: Delayed Delivery • NServiceBus • Particular Docs

I haven’t seen this in the documentation? We are using SQL Server.

It’s the limits of your selected Persistence, so it is something you need to read in the documentation of the Persistence. I don’t think SQL Server would be a problem, but it also has its limit on what you can store in a column.