What's the proper way to abandon an Azure SB Message so that it becomes visible again in the future in a way I can control?

Drew Marsh picture Drew Marsh · Apr 30, 2013 · Viewed 7.4k times · Source

So the scenario is that I'm using an SB queue to throttle outgoing callbacks to other services. One of the standard problems with calling back to other services is that they may be down for uncontrollable amounts of time. Assuming I detect that the target is down/not responding, what is the best pattern for abandoning that message so that it doesn't reappear on the queue immediately?

Here's are some approaches I'm either aware of, have tried or am considering:

  • Obviously if I just use BrokeredMessage::Abandon() the message will be unlocked and put back on the queue. This is obviously undesirable for this scenario and what I'm trying to avoid.

  • If I just ignore the fact that I ran into an error and never call Abandon this will keep it from showing up immediately, but I don't really have fine grained control over how long until it shows up again and I would like to implement a decaying retry strategy.

  • I thought maybe I could call BrokeredMessage::Abandon(IDictionary<string, object>) and somehow update the ScheduledEnqueueTimeUTC property, but I have tried this and there doesn't seem to be a way to affect that property beyond the initial sending of the message. Makes sense, but thought worth a try.

  • I have considered just using BrokeredMessage::Complete() in this situation and actually just enqueueing a new copy of the message with the ScheduledEqueueTimeUTC property set.

The final bullet almost seems too heavy handed, but I'm coming to the conclusion it's probably the right answer given the inherent nature of queues. I just figured there might be a nicer way to do this within Azure SB queues that I'm missing.

Answer

Clemens Vasters picture Clemens Vasters · Apr 30, 2013

If you want to put a message away for a while and you have a place to write down the SequenceNumber (which might be in Session state in a sessionful queue), you can Defer() it. Deferred messages can be retrieved using a special Receive overload giving the SequenceNumber; that's also the only way to get at them again other than them expiring, so careful. This feature was built for workflows and state machines so that they can deal with out of order message arrival.