Azure / azure-sdk-for-python

This repository is for active development of the Azure SDK for Python. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/python/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-python.
MIT License
4.55k stars 2.77k forks source link

Why Python sdk does't have RegisterMessageHandler method like C# has? #10098

Closed TzlilSwimmer123 closed 4 years ago

TzlilSwimmer123 commented 4 years ago

Describe the bug I want to get a in my Flask application a message every time I send it. With get_receiver I can only get it once per program running. I saw that C# Subscription client has RegisterMessageHandler that make the program listen to the topic and waits to a message being sent. There is a reason why Python sdk does not have such a thing?

kaerm commented 4 years ago

Hey @TzlilSwimmer123 thanks for reaching out to us, looping in our team to take a look at this //cc: @KieranBrantnerMagee

yunhaoling commented 4 years ago

Hi @TzlilSwimmer123 , thanks for bringing up this topic.

We're having internal discussion on whether to introduce the push mode (register a callback method to handle messages and keep receiving) into our sdk. Your thoughts on this are most welcome:

We're looking forward to your thoughts!

TzlilSwimmer123 commented 4 years ago

Hi @yunhaoling , thanks for your response

User picks all the things he want to delete ---> we update our table with the object state ---> we send a message to the topic ----> we WANT to get that message without pulling it and use its data in order to delete the corresponding chunk (by id for example). We need to get the message every time it gets into the topic and not wait for pulling it with "get_receiver" method.

Thanks, Tzlil

yunhaoling commented 4 years ago

@TzlilSwimmer123 , thanks for the feedback, I agree that registering a callback is a commonly used pattern to receive messages from messaging services and makes things easy.

We'll take your thoughts into consideration, thanks!

note: although we don't have "listen" api in current sdk, the receiver itself is a "generator" which runs forever until forced/asked to stop.

You can take a look at the sample code here: https://github.com/Azure/azure-sdk-for-python/blob/c0d185ed7c8666d4916fec8021b7d118ec8e0061/sdk/servicebus/azure-servicebus/samples/sync_samples/example_queue_send_receive_batch.py#L39-L44

TzlilSwimmer123 commented 4 years ago

@yunhaoling I am not sure how the "generator" can help me in my situation. When I used this bit of code I did not get messages in real time...

Thanks

yunhaoling commented 4 years ago

Hello @TzlilSwimmer123 , Sorry for not getting back to you sooner.

I read your case again in detail and it looks to me that the major goal you want to achieve is "sdk not blocking" -- "do it without delaying the user until the process is done".

My following thoughts are:

TzlilSwimmer123 commented 4 years ago

Hi @yunhaoling when I used python I tried:

Receive messages as a continuous generator

for message in receiver: print("Message: {}".format(message)) print("Sequence number: {}".format(message.sequence_number)) message.complete() total += 1

Now I am using the JS skd, using the RegisterMessageHandler. Does this handler uses an another thread? I really don't know.

I just want to get subscription messages on real time when they sent to the subscription without pulling them manually. Exactly what RegisterMessageHandler does.

Thanks, Tzlil

KieranBrantnerMagee commented 4 years ago

Hey Tzlil, To be clear, using the generator is effectively real-time. This is an interesting statement to make in Python because it is effectively single threaded, so if one receive thread (whether we used a callback or the generator where you spun off your own processor thread, it wouldn't matter, they're effectively isomorphic concepts) blocks for a time, then you'll receive whatever messages arrived in the interim once the receiver thread is able to run again. JavaScript will have a similar constraint, although it may be less obvious since they're using a callback.

So to be very concrete: if you wanted callback-esque behavior, simply start your own worker thread on every iteration of the "for message in receiver" loop.

To be precise as well, since earlier you mention "get_receiver" and I wanted to make sure we were on the same page, you'd only call that once, to get the receiver itself. Once you have the receiver, you can effectively sit in the generator (for message in receiver) forever and continually receive incoming messages.

Finally, I'll cap this with some info you might be interested in: We're currently in the process of deprecating this version (0.50) in order for the GA version of the library (7.0.0, currently in preview b1). I've tagged this as a feature request, and while I'll be closing this now, will be logging it to reference with our design discussions and may reopen if we find that users as a whole would lean towards Callbacks, it's very useful to hear that you were expecting that sort of behavior.

Don't hesitate to reopen/reach out with any further questions, -Kieran