FoundatioFx / Foundatio.AzureServiceBus

Foundatio Azure ServiceBus
Apache License 2.0
19 stars 15 forks source link

Using ReceiveMode.PeekLock on the service bus #38

Open jcono opened 3 years ago

jcono commented 3 years ago

I will let you know once I have tested but it's my understanding that the combination of ReceiveMode.PeekLock and MessageHandlerOptions.AutoComplete used when registering the message handler will result in SubscriptionClient.CompleteAsync being called once the handler successfully completes.

The source code for the message pump used by the subscription client would suggest this is the case too.

So as far as I can tell the message would be deleted from the queue so long as the registered handler doesn't throw an exception. At least that's how the comments in the code read (the Microsoft documentation is a little light on detail).

What I don't know yet is what happens in the event of an exception in the handler (meaning the message remains on the queue) and whether that message then gets delivered again (to the same receiver) once the peek lock is abandoned. For our usage I'm hoping it does.

Originally posted by @jcono in https://github.com/FoundatioFx/Foundatio.AzureServiceBus/issues/37#issuecomment-863602082

jcono commented 3 years ago

Just following up with a bit more information.

This turns out to be harder than I'd hoped which might have more to do with the architecture of Foundatio MessageBus abstraction than anything else so I'm wondering if there's a way forward.

Using PeekLock doesn't create any problems at all it's just that any exception thrown by a handler registered using IMessageBus.SubscribeAsync is wrapped by the framework (I think to support its abstraction).

Specifically in this case the handler that runs when a message is received on the service bus is in AzureServiceBusMessageBus.OnMessageAsync which in turns hands it off to the MessageBusBase.SendMessageToSubscribers. The problem is that this method is responsible for sending the message to all subscribers and launches that work asynchronously and returns. This means that none of the subscriber handlers have a chance to throw an exception. Either way, currently any exception is swallowed (and logged) by the task that is run.

I think means that the underlying framework would need to change. My apologies as I'm not that familiar with it all yet but perhaps some option in SharedMessageBusOptions to distribute messages synchronously (and not swallow the exception)? That might allow the SendMessageToSubscribers method to be reworked to run the handlers in sequence and have any exception propagate up?

If I have time I might create a PR for this but will probably wait to hear any thoughts first.