DelayDeliveryWith, how many times?

When I use DelayDeliveryWith to delay a command, can I somehow read in the message headers how many times it has been delayed?

       var sendOptions = new SendOptions();
       sendOptions.DelayDeliveryWith(TimeSpan.FromSeconds(10));
       return context.Send(command, sendOptions);

You’re conflating two things: delaying message delivery vs retries.

sendOptions.DelayDeliveryWith indicates how long to delay a message before it shows up on the queue, not how many times the message is received. The delay will take place once and once only. Every subsequent retry of the message will be w/o delay since the message has been delayed already.

If you want to know how many times a message has been retried, see the headers docs for that.

You’re conflating two things: delaying message delivery vs retries.

No, actually I am aware of the differences and know that the header “NServiceBus.Retries” is tied to the error handling.

But I need similar metadata for intentionally delayed delivery, when I re-send a Message (expecting it to be handled by the same MessageHandler later in time). I could add a property in the Message it self, but don’t like the idea. Maybe NSB was tracking this in the metadata.

Delayed Delivery is a delivery mechanism. Re-sending a message is a logical operation. You send a brand new message each time. This is why I pointed out the difference between delayed delivery and retries.

If you’d describe your exact scenario, it would be easier to understand what you’re after.

Plain simple. I would like to increase the delay each time it is re-send.

var sendOptions = new SendOptions();
sendOptions.DelayDeliveryWith(TimeSpan.FromSeconds(10));
return context.Send(command, sendOptions);

Your message is sent from the user code once and retried by NServiceBus/infrastructure as frequently as recoverability is configured. What NServiceBus allows you is to set the backoff time for delayed retries. That’s because each delayed retry message is a brand new message, and the delay can be set when it’s enqueued. Your sending code is no longer involved once a message is successfully dispatched for the first time. So I’m not sure how you see that code changing the delay.

Let me explain.

  1. MessageHandler receives a message.

  2. MessageHandler re-send the message with a delay.

  3. Same MessageHandler will receive the delayed copy of original Message

  4. MessageHandler re-send the message again with a even larger delay.

  5. Same MessageHandler recieves message. Some state is now present, and the message is not re-send, ending the recursive loop.

In step 4, how would i increase the delay here?

The handler sending the message is the one that will receive it. Ok, that’s a bit better than the description earlier.

Every time a handler receives a message, it will be a brand-new message unless it’s a retry. You’ll need to explicitly populate the new message with the header or the data upon sending it. For initial message, it would be “delayed-with: x”. And when you handle the message, you read the header and add to x an additional value. For example:

var sendOptions = new SendOptions();
sendOptions.SetHeader("delayed-with", x);
await context.Send(command, sendOptions);

I’m just wondering if this is really necessary or, rather, this is a process and you should be looking at Saga.

Actually I was advised to look into delayed delivery, in stead of using a saga.

Delay command via saga

You’ve got the options. The world is your oyster!

It sounds like what you’re looking for might be a custom recoverability policy.

Is that it?

Actually I considered using error retries, but thought it would be the wrong tool here. Also it wold nice to have the delay logic placed in the MessageHandler class.