diff options
author | Andy McCurdy <andy@andymccurdy.com> | 2014-05-06 22:44:19 -0700 |
---|---|---|
committer | Andy McCurdy <andy@andymccurdy.com> | 2014-05-06 22:44:19 -0700 |
commit | ef053647bb834782cde43e6d5b1f829d64646a42 (patch) | |
tree | 7c4fa321f4dca5b680549a5f47274c016165296c /redis/sentinel.py | |
parent | bb37148294e9b91c1da872a84a7bf217c15b064d (diff) | |
download | redis-py-ef053647bb834782cde43e6d5b1f829d64646a42.tar.gz |
SentinelManagedConnections to master servers disconnect on READONLY errors.
Any attempt to reconnect will force all connections in that pool to update
their connections to the new master. Fixes #435
Diffstat (limited to 'redis/sentinel.py')
-rw-r--r-- | redis/sentinel.py | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/redis/sentinel.py b/redis/sentinel.py index e124f29..b541686 100644 --- a/redis/sentinel.py +++ b/redis/sentinel.py @@ -4,7 +4,7 @@ import weakref from redis.client import StrictRedis from redis.connection import ConnectionPool, Connection -from redis.exceptions import ConnectionError, ResponseError +from redis.exceptions import ConnectionError, ResponseError, ReadOnlyError from redis._compat import xrange, nativestr @@ -42,6 +42,20 @@ class SentinelManagedConnection(Connection): continue raise SlaveNotFoundError # Never be here + def send_command(self, *args): + try: + super(SentinelManagedConnection, self).send_command(*args) + except ReadOnlyError: + if self.connection_pool.is_master: + # When talking to a master, a ReadOnlyError when likely + # indicates that the previous master that we're still connected + # to has been demoted to a slave and there's a new master. + # calling disconnect will force the connection to re-query + # sentinel during the next connect() attempt. + self.disconnect() + raise ConnectionError('The previous master is now a slave') + raise + class SentinelConnectionPool(ConnectionPool): """ @@ -66,12 +80,12 @@ class SentinelConnectionPool(ConnectionPool): def get_master_address(self): master_address = self.sentinel_manager.discover_master( self.service_name) - if not self.is_master: - pass - elif self.master_address is None: - self.master_address = master_address - elif master_address != self.master_address: - self.disconnect() # Master address changed + if self.is_master: + if self.master_address is None: + self.master_address = master_address + elif master_address != self.master_address: + # Master address changed, disconnect all clients in this pool + self.disconnect() return master_address def rotate_slaves(self): |