rebus-org / Rebus.AzureServiceBus

:bus: Azure Service Bus transport for Rebus
https://mookid.dk/category/rebus
Other
33 stars 20 forks source link

Best way to handle failed messages #81

Closed alexanderbikk closed 2 years ago

alexanderbikk commented 2 years ago

I'm looking for the best way of handling failed messages in Rebus when Service Bus used. I would like to handle message directly in my application. For example read dead letter queue, process message and remove it.

I see two options:

  1. Native dead letter queue
  2. Rebus error queue

Regarding the first option. I'm wondering is it possible to handle dead lettered message in Rebus when UseNativeDeadlettering() configured? I assume the only way to do it is using the native Serves Bus SDK client and process messages from dead letter queue, right?

Regarding the second option. Is it possible to manage Rebus error queue somehow? Is it possible to have a handler for Rebus error queue, which will process message (re-route etc.) and delete it from queue?

I see that it's possible to enable second-layer retries. But looks like it's processing on the fly until message will be dead lettered in error queue. Then will it be possible to delete message in Handle(IFailed<DoStuff> failedMessage) instead of Deffer() and DeadLetter() (btw can't see this method anymore)? Or Deffer() and then delete somehow after certain retries.

Thanks in advance.

mookid8000 commented 2 years ago

There's no way currently, to make Rebus receive messages from ASB's native dead-letter queue.

So your best bet is probably to have Rebus dead-letter messages as it does by default, i.e. by moving them to the "error" queue, and then you can just spin up another Rebus instance that receives messages from that.

If you want your dead-letter processor to be more generic, you might want to have it skip trying to deserialize the messages - this can be done e.g. by utilizing a transport message forwarder, which is a generic handler that is invoked BEFORE the more sophisticated parts of the message handling pipeline get invoked.

A transport message forwarder can inspect message headers, look at the message payload in the form of a byte[], and possibly forward one or more copies of it to other queues. Or you could stash the message in a database, or whatever you feel like doing. πŸ™‚ Or you could of course also become a Rebus Pro subscriber, which would relieve your dead-lettering headache once and for all. πŸ˜‰

alexanderbikk commented 2 years ago

I think transport message forwarder is not what I'm looking for. The handler of my subscriber should process messages. But it obviously could be failed messages. So I would like to handle them in a separate handler of the same subscriber as well.

So your best bet is probably to have Rebus dead-letter messages as it does by default, i.e. by moving them to the "error" queue, and then you can just spin up another Rebus instance that receives messages from that.

How can I do it in asp.net core? I see the beta version of ServiceProvider now supports something like this. Is it the best way to do it? Is using beta safe enough? :)

Also, is it possible to use second-level retries for it? I was thinking of handling failed messages and Delete() them somehow. Like in your doc. I see example with Deffer() and Deadletter(). But no way to delete the message in _bus.Advanced.TransportMessage. Is it possible to delete the message in Handle(IFailed<DoStuff> failedMessage)?

Maybe Rebus Pro is an option. But I'm not the guy who decides :)

mookid8000 commented 2 years ago

How can I do it in asp.net core? I see the beta version of ServiceProvider now supports something like this. Is it the best way to do it? Is using beta safe enough? :)

It's definitely an easy way to do it, and yes it's safe! I mean, I cannot guarantee that it doesn't contain bugs, but I can say with a pretty high degree of certainty that bugs (if any) will pertain to the management of the container registrations and not to the bus, so if you succeed in starting a bus instance πŸ˜… I am pretty sure it will not do anything bad(*)

Also, is it possible to use second-level retries for it?

It would definitely also be possible, yes.

(..) But no way to delete the message in _bus.Advanced.TransportMessag

But you simply "delete" a message by handling it without any exceptions. And you avoid deleting messages by throwing exceptions. Pretty simple: 1: Exception πŸ‘‰ message is preserved (retried a bunch of times, then moved to dead-letter queue), 2: No exception πŸ‘‰ message considered correctly handled i.e. message is gone and that also holds for the 2nd level retries.

If you're interested in trying the cloud-hosted Fleet Manager for free, I can invite you into the TEST environment. If you send an email to mogens@rebus.fm I can set you up as a team admin, and then you can invite your colleagues in.


(*) As always, there's no guarantee when using free open-source software from the internet.

alexanderbikk commented 2 years ago

It's definitely an easy way to do it, and yes it's safe! I mean, I cannot guarantee that it doesn't contain bugs, but I can say with a pretty high degree of certainty that bugs (if any) will pertain to the management of the container registrations and not to the bus, so if you succeed in starting a bus instance πŸ˜… I am pretty sure it will not do anything bad(*)

I got it :)

But you simply "delete" a message by handling it without any exceptions. And you avoid deleting messages by throwing exceptions. Pretty simple: 1: Exception πŸ‘‰ message is preserved (retried a bunch of times, then moved to dead-letter queue), 2: No exception πŸ‘‰ message considered correctly handled i.e. message is gone and that also holds for the 2nd level retries.

I have already tried this solution. And it works good for our case. Thanks.

If you're interested in trying the cloud-hosted Fleet Manager for free, I can invite you into the TEST environment. If you send an email to mogens@rebus.fm I can set you up as a team admin, and then you can invite your colleagues in.

Good to know. But I think we have plans to use only opensource version... Which is great btw! Sorry :)

Thanks a lot!

mookid8000 commented 1 year ago

Yes the new Rebus.ServiceProvider has built in support for hosting multiple bus instances, so it would be easy to just start one with queue β€œerror”.

And yes, 2nd level retries could also be used. You β€œdelete” the message by handling it without exceptions. πŸ™‚

Sendt fra min iPhone

– Mogens Heller Grabe Torsmark 4 8700 Horsens Danmark

+45 29367077 @.***

Den 11. maj 2022 kl. 19.58 skrev Alexander @.***>:

ο»Ώ I think transport message forwarder is not what I'm looking for. The handler of my subscriber should process messages. But it obviously could be failed messages. So I would like to handle them in a separate handler of the same subscriber as well.

So your best bet is probably to have Rebus dead-letter messages as it does by default, i.e. by moving them to the "error" queue, and then you can just spin up another Rebus instance that receives messages from that.

How can I do it in asp.net core? I see the beta version of ServiceProvider now supports something like this. Is it the best way to do it?

Also, is it possible to use second-level retries for it? I was thinking of handling failed messages and Delete() them somehow. Like in your doc. I see example with Deffer() and Deadletter(). But no way to delete the message in _bus.Advanced.TransportMessage.

β€” Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you modified the open/close state.