azure-service-bus-dotnet icon indicating copy to clipboard operation
azure-service-bus-dotnet copied to clipboard

More control over abandoned messages

Open ddobric opened this issue 8 years ago • 15 comments

Hi all,

Sometimes business logic decides that it would be good to retry a message at some latter time. For this reason it would be very helpful, if Abandon(IDictionary<>) or similar, would be able to set ScheduledEnqueueTimeUtc.

msg.Abandon(new Dictionary<string, object>()
{
  { "ScheduledEnqueueTimeUtc", DateTime.Now.ToUniversalTime().AddMinutes(2) }
});

Right now, this does not work, because only custom properties can be manipulated this way. I’m also happy to hear if this kind of retry can be achieved on some other easier way? Right now, I typically set LockDuration on some reasonable retry time and avoid invoking of abandon in PeekLock mode. Another way is Deferring, but I don’t like it, because it requires me track deferred message, which makes things more complicate then necessary.

To recap all, wouldn’t be good to have something between Deferr() and Abandon()? For example Defer(TimeSpan) or Defer(ScheduleteTimeUtc) or Abandon(TimeSpan) or Abandn(TimeSpan)?! Only difference would be, that in a case of Defer, property DeliveryCount wouldn’t be incremented.

Regards Damir

ddobric avatar Dec 22 '16 17:12 ddobric

Great suggestion. Also would cut down amount of work that has to be done today on the client-side to get a workaround.

SeanFeldman avatar Dec 22 '16 18:12 SeanFeldman

+1 from me.

It's a non-trivial thing to do this unless you're using the built-in lock time of the message and simply not abandoning it (so it times out and is picked up again). This method has several drawbacks because you can only have 7 minutes lock time (sometimes you want to wait longer before retrying) and a message also has a max retry count (sometimes you want to retry within a time frame and don't care so much about the number of retries).

To be honest I don't really understand where Defer() would be safe to use if it's not combined with a permanent store like a database. If you defer a message and your VM/App is recycled you lose that message forever.

Defer(TimeSpan) or Defer(ScheduleteTimeUtc) sounds perfect. Or maybe a separate method like Reschedule(ScheduleTimeUtc).

HansOlavS avatar Jan 03 '17 09:01 HansOlavS

Regarding Defer(), you are right. But this is an additional required improvement. Defer introduce more problems than it helps, in that case. My intension around Abandon() is to provide us features, which do not require so much programming and introducing additional artifacts like DB. With Deffer(TimeSpan), I mean postponing of the message at scheduled time, without of need to keep reference of it.

ddobric avatar Jan 04 '17 09:01 ddobric

can this be achieved by re-send the current messages as scheduled messages and complete the current message?

binzywu avatar Jan 06 '17 18:01 binzywu

@binzywu it introduced overhead that needs to be taken into consideration and coded each time. Because it's no longer a single message based operation, you need to have a transaction. Rather than just using Defer(timespan). Also, from a tracking point of view, you want to handle the same message, just later. Saying that, @djrosanova made a good point saying that ASB doesn't mutate messages. But in this case, it would not be exactly a mutation, if broker is instructed to defer the processing.

SeanFeldman avatar Jan 06 '17 23:01 SeanFeldman

@ddobric - This is something that we can revisit when both .NET Core and AMQP support transactions. We could easily implement a method to do what you are talking about. We would create a transaction, complete the message, and send a scheduled message.

jtaubensee avatar Jan 26 '17 22:01 jtaubensee

@jtaubensee I think you wanted to link to issue #6? 😉

SeanFeldman avatar Jan 27 '17 00:01 SeanFeldman

Would this be considered for 1.0.0 or later?

SeanFeldman avatar Jul 26 '17 23:07 SeanFeldman

Like mentioned here , this would require AMQP transactions to be implemented first. Unfortunately, this would not make it to 1.0.0.

nemakam avatar Jul 26 '17 23:07 nemakam

Thanks @nemakam. Skipped that comment. So it could be then added to the 2.0.0 milestone or 2.x in case it has to be done after #6 is finished.

SeanFeldman avatar Jul 27 '17 00:07 SeanFeldman

This issue has been added to milestone backlog. Given that we haven't planned for this feature yet, it might not be right to assign 2.0 milestone for this issue yet.

nemakam avatar Jul 27 '17 00:07 nemakam

I'll need this feature as it will be blocking for scenarios where a message needs to be delayed and the original message ID has to be kept, but native-dedup is in place. A workaround suggested here

Complete the message and schedule another message for 5 mins later.

would not work.

SeanFeldman avatar May 25 '18 22:05 SeanFeldman

Server side work is tracked here.

SeanFeldman avatar Jun 11 '18 18:06 SeanFeldman

We need this feature as well. I am trying to stay with a Microsoft stack, but it is difficult when the applications have to manage the scheduling and DLQ to get functionality that would be solved with a Defer(datetime) or Defer (timespan). Without it, the automatic DLQ functionality is not useful and we had to code logic to know when to dead letter a message.

DanCaveman avatar Jul 10 '18 15:07 DanCaveman

What is the latest on this feature? This seems like a no-brainer feature for queue work. Thanks.

gdodd1977 avatar Dec 13 '18 22:12 gdodd1977