aio-libs-abandoned / aioredis-py

asyncio (PEP 3156) Redis support
https://aioredis.readthedocs.io/
MIT License
2.3k stars 336 forks source link

await asyncio.create_task(pubsub.run()) gives RuntimeError if no subscriptions are present #1234

Open dnlwgnd opened 2 years ago

dnlwgnd commented 2 years ago

Describe the bug

I am using aioredis as a redis client in an async FastAPI app. In a specific usecase I do have a websocket server-endpoint in which I want to listen for subscribe-messages (that is just a json string) from my websocket-client. I then need to setup a pubsub instance with the appropriate subscriptions for which I want to supply an callback handler function. Those subscribe-messages can come at any point in time, so especially in the very beginning there is no subscription at all (until I receive the first such message)

A the time the websocket session opens, I also create the pubsub object via redis_client.pubsub(). I also submit a task to the asyncio event queue for the pubsub.run() function, that is supposed to call my callback of the subscriptions.

Now I do get an error when creating that task:

 File "......py", line 164, in websocket_endpoint
    await asyncio.create_task(pubsub.run())
  File "..../lib/python3.10/site-packages/aioredis/client.py", line 4215, in run
    await self.get_message(
  File "..../lib/python3.10/site-packages/aioredis/client.py", line 4116, in get_message
    response = await self.parse_response(block=False, timeout=timeout)
  File ".../lib/python3.10/site-packages/aioredis/client.py", line 3989, in parse_response
    raise RuntimeError(
RuntimeError: pubsub connection not set: did you forget to call subscribe() or psubscribe()?

I do not get an error, if I setup one or more subscriptions in the pubsub instance before calling run(). However, I feel this should still be possible and should not give an error.

To Reproduce

This is what I do in a standard asyncio environment:

redis_client = aioredis.from_url(url='redis://localhost:6379',decode_responses=True)
pubsub = redis_client.pubsub()
await asyncio.create_task(pubsub.run())

Expected behavior

The run() task should just run, even if there are no subscriptions and thus no handlers available.

Logs/tracebacks

see above

Python Version

$ python --version
Python 3.10.0

aioredis Version

$ python -m pip show aioredis
Version: 2.0.0

Additional context

No response

Code of Conduct

Andrew-Chen-Wang commented 2 years ago

I believe this is intended redis-py implementation. Are you able to reproduce on redis-py? If so, please file there as we will follow suit. I don't really have an opinion on this (nor the time at the moment). Please cc me via the @ symbol!