Search code examples
pythonredisredis-py

Redis PubSub not reconnecting


I am currently developping a wrapper around Redis Pubsub to get a Subscriber instance. I am trying to make it robust to Connection interruptions. As per the documentation, "In the event of a disconnection such as a network error or timeout, the PubSub object will re-subscribe to all prior channels and patterns when reconnecting". But it doesn't seem to work for me.

Here's a working example of a PubSub process:

>>> import redis
>>> r = redis.Redis(host="172.17.0.2", port=6379)
>>> r.ping()
True
>>> sub = r.pubsub()
>>> sub.subscribe("test")
>>> r.publish("test","test")
1
>>> sub.get_message()
{'type': 'subscribe', 'pattern': None, 'channel': b'test', 'data': 1}
>>> sub.get_message()
{'type': 'message', 'pattern': None, 'channel': b'test', 'data': b'test'}

At this point, I shutdown my Redis instance. r.ping() results in a redis.exceptions.ConnectionError as expected.

At this point, I restart my Redis instance.

>>> r.ping()
True
>>> r.publish("test","test")
0
>>> sub.get_message()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/robin/.conda/envs/rb-linkvision/lib/python3.6/site-packages/redis/client.py", line 3617, in get_message
    response = self.parse_response(block=False, timeout=timeout)
  File "/home/robin/.conda/envs/rb-linkvision/lib/python3.6/site-packages/redis/client.py", line 3503, in parse_response
    if not block and not conn.can_read(timeout=timeout):
  File "/home/robin/.conda/envs/rb-linkvision/lib/python3.6/site-packages/redis/connection.py", line 734, in can_read
    return self._parser.can_read(timeout)
  File "/home/robin/.conda/envs/rb-linkvision/lib/python3.6/site-packages/redis/connection.py", line 321, in can_read
    return self._buffer and self._buffer.can_read(timeout)
  File "/home/robin/.conda/envs/rb-linkvision/lib/python3.6/site-packages/redis/connection.py", line 231, in can_read
    raise_on_timeout=False)
  File "/home/robin/.conda/envs/rb-linkvision/lib/python3.6/site-packages/redis/connection.py", line 201, in _read_from_socket
    raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR)
redis.exceptions.ConnectionError: Connection closed by server.

It seems the Redis connection has correctly been re-enabled, but the PubSub instance doesn't work anymore. I am then currently using a workaround.

>>> sub.reset()
>>> sub.subscribe("test")
>>> sub.get_message()
{'type': 'subscribe', 'pattern': None, 'channel': b'test', 'data': 1}

I am happy with my workaround, but the documentation clearly states that this should be handled automatically. Is there something that I don't do correctly ? Thanks for your answers !


Solution

  • Creating the redis client with the health_check_interval option did the trick.