-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrong order of callbacks #90
Comments
Protocol wise the message will be delivered with respective to the order in which the messages were published and asyncio will dispatch for the callback that is ready. In your example the B messages will be delivered before C and A. If the callbacks relinquish control so that other tasks can process messages then you would see that the messages are processed in that order:
|
But if we add one more sleep to one of callbacks, situation changes:
then log looks like:
This is more common situation because callbacks in real case have more returns into loop. |
Right, because when the B handler starts processing the messages it will continue to do so until it the event loop allows other callback to execute (https://github.com/nats-io/asyncio-nats/blob/master/nats/aio/client.py#L529-L549). But internally the messages have been received in the same order as the source, if you relinquishing control as part of the callback using |
I found, that socket receives messages in right order, but in real case callbacks comes in random order, and it completely unusable to publish messages with different topics in loop - for example if I have two subjects - create_user and set_user_password - then often second topic comes before first, and trying to setup password to user which not created yet. Btw, for same subject callbacks always work in right order. |
For that type of usage I'd recommend using request/response functionality from the client as it would give you a stronger ordering guarantee and better decoupling with the subscribers, sharing an example below: Subscribers: import asyncio
import time
from nats.aio.client import Client as NATS
async def run(loop):
await nc.connect("demo.nats.io", loop=loop)
async def create_user(msg):
print(f'create_user : {msg}')
await nc.publish(msg.reply, b'user created')
async def set_user_password(msg):
print(f'set_user_password: {msg}')
await nc.publish(msg.reply, b'password set')
await nc.subscribe("create_user", cb=create_user)
await nc.subscribe("set_user_password", cb=set_user_password)
if __name__ == '__main__':
nc = NATS()
loop = asyncio.get_event_loop()
loop.run_until_complete(run(loop))
loop.run_forever() Publish: import asyncio
from nats.aio.client import Client as NATS
async def run(loop):
await nc.connect("demo.nats.io", loop=loop)
for i in range(10):
response = await nc.request("create_user", f"user:user-{i}".encode())
print(f"Result [{i}]: {response.data.decode()}")
response = await nc.request("set_user_password", f"password:foo".encode())
print(f"Result [{i}]: {response.data.decode()}")
if __name__ == '__main__':
nc = NATS()
loop = asyncio.get_event_loop()
loop.run_until_complete(run(loop))
loop.run_forever() Result:
|
I've found that asyncio.Lock doing job. I added lock around callbacks which should run in ordered way. |
Closing as that is how the client is intended to work right now (similar behavior as in the Go client). |
Hello,
NATS documentation says, that messages from one publisher are received in the same order as they were published. But if we make few subscriptions, and publish messages for each one few times, callbacks will be called in different order. This is because each subscriber has own message queue. Here is example:
receive.py
publish.py:
Just run publish.py after receive.py.
The text was updated successfully, but these errors were encountered: