aredis: PubSub get_message() not always returns None when there're no data available

Hello Jason,

Looks like PubSub get_message() function is not working as expected, on just created channel without no data. I assume that call of this method should return None in that case, however None returns only once and then execution “hangs” and awaits for coroutine to be completed (actual data appears in the channel) and then execution continues.

Here are the steps to reproduce this issue:

# 1. Create some subscription (PubSub obj)

# redis — initialized connection to some Redis instance
pbsb = redis.pubsub(ignore_subscribe_messages=True)
await pbsb.subscribe("some-channel")

# 2. Query message in the loop
timeout = 5
message = None
end_time = time.time() + timeout
while timeout == 0 or time.time() < end_time:
    print(1)
    message = await pbsb.get_message(timeout=1)
    print(2)

# 3. results
>>> 1
>>> 2
>>> 1
# these should be a little more 1 and 2 :)

# 4. Nothing more happened until some data arrives, then
>>> 2

I’ve attached a patch addressed to resolve this issue, it removes connection.can_read() check in aredis/pubsub.py on line 132, because in that case it always returns False and adds several imports:

from aredis.exceptions import ConnectionError
from aredis.exceptions import TimeoutError

Looks like without them except on line 112 is not working as expected.

Also in aredis/connection.py on line 307 I’ve added check

if not self._reader:
    break

Because when coroutine actually cancelled, self._reader is getting None and this is leads to unwanted exception.

Best, Jack

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 16 (16 by maintainers)

Commits related to this issue

Most upvoted comments

Hi Jason,

I’ve created a test repo and in this test code everything is working fine: no leaks, correct app termination.

I’ll double check my project code tomorrow and let you know about results. Thank you for the patience and help.

Best, Jack

Hi Jason,

I’ve checked this code, it’s always False for me.

await connection.can_read(timeout=timeout)

Also looks like this guy

bool(select([sock], [], [], timeout)[0])

Works really slow and raises warning I’ve previously mentioned.

Best, Jack