diff options
Diffstat (limited to 'redis')
-rwxr-xr-x | redis/client.py | 21 | ||||
-rwxr-xr-x | redis/connection.py | 27 | ||||
-rw-r--r-- | redis/retry.py | 8 |
3 files changed, 45 insertions, 11 deletions
diff --git a/redis/client.py b/redis/client.py index c7aa17b..0236f20 100755 --- a/redis/client.py +++ b/redis/client.py @@ -869,6 +869,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): errors=None, decode_responses=False, retry_on_timeout=False, + retry_on_error=[], ssl=False, ssl_keyfile=None, ssl_certfile=None, @@ -887,8 +888,10 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): ): """ Initialize a new Redis client. - To specify a retry policy, first set `retry_on_timeout` to `True` - then set `retry` to a valid `Retry` object + To specify a retry policy for specific errors, first set + `retry_on_error` to a list of the error/s to retry on, then set + `retry` to a valid `Retry` object. + To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. """ if not connection_pool: if charset is not None: @@ -905,7 +908,8 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): ) ) encoding_errors = errors - + if retry_on_timeout is True: + retry_on_error.append(TimeoutError) kwargs = { "db": db, "username": username, @@ -914,7 +918,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): "encoding": encoding, "encoding_errors": encoding_errors, "decode_responses": decode_responses, - "retry_on_timeout": retry_on_timeout, + "retry_on_error": retry_on_error, "retry": copy.deepcopy(retry), "max_connections": max_connections, "health_check_interval": health_check_interval, @@ -1146,11 +1150,14 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands): def _disconnect_raise(self, conn, error): """ Close the connection and raise an exception - if retry_on_timeout is not set or the error - is not a TimeoutError + if retry_on_error is not set or the error + is not one of the specified error types """ conn.disconnect() - if not (conn.retry_on_timeout and isinstance(error, TimeoutError)): + if ( + conn.retry_on_error is None + or isinstance(error, tuple(conn.retry_on_error)) is False + ): raise error # COMMAND EXECUTION AND PROTOCOL PARSING diff --git a/redis/connection.py b/redis/connection.py index 3fe8543..a349a0f 100755 --- a/redis/connection.py +++ b/redis/connection.py @@ -513,6 +513,7 @@ class Connection: socket_keepalive_options=None, socket_type=0, retry_on_timeout=False, + retry_on_error=[], encoding="utf-8", encoding_errors="strict", decode_responses=False, @@ -526,8 +527,10 @@ class Connection: ): """ Initialize a new Connection. - To specify a retry policy, first set `retry_on_timeout` to `True` - then set `retry` to a valid `Retry` object + To specify a retry policy for specific errors, first set + `retry_on_error` to a list of the error/s to retry on, then set + `retry` to a valid `Retry` object. + To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. """ self.pid = os.getpid() self.host = host @@ -543,11 +546,17 @@ class Connection: self.socket_type = socket_type self.retry_on_timeout = retry_on_timeout if retry_on_timeout: + # Add TimeoutError to the errors list to retry on + retry_on_error.append(TimeoutError) + self.retry_on_error = retry_on_error + if retry_on_error: if retry is None: self.retry = Retry(NoBackoff(), 1) else: # deep-copy the Retry object as it is mutable self.retry = copy.deepcopy(retry) + # Update the retry's supported errors with the specified errors + self.retry.update_supported_erros(retry_on_error) else: self.retry = Retry(NoBackoff(), 0) self.health_check_interval = health_check_interval @@ -969,6 +978,7 @@ class UnixDomainSocketConnection(Connection): encoding_errors="strict", decode_responses=False, retry_on_timeout=False, + retry_on_error=[], parser_class=DefaultParser, socket_read_size=65536, health_check_interval=0, @@ -978,8 +988,10 @@ class UnixDomainSocketConnection(Connection): ): """ Initialize a new UnixDomainSocketConnection. - To specify a retry policy, first set `retry_on_timeout` to `True` - then set `retry` to a valid `Retry` object + To specify a retry policy for specific errors, first set + `retry_on_error` to a list of the error/s to retry on, then set + `retry` to a valid `Retry` object. + To retry on TimeoutError, `retry_on_timeout` can also be set to `True`. """ self.pid = os.getpid() self.path = path @@ -990,11 +1002,17 @@ class UnixDomainSocketConnection(Connection): self.socket_timeout = socket_timeout self.retry_on_timeout = retry_on_timeout if retry_on_timeout: + # Add TimeoutError to the errors list to retry on + retry_on_error.append(TimeoutError) + self.retry_on_error = retry_on_error + if self.retry_on_error: if retry is None: self.retry = Retry(NoBackoff(), 1) else: # deep-copy the Retry object as it is mutable self.retry = copy.deepcopy(retry) + # Update the retry's supported errors with the specified errors + self.retry.update_supported_erros(retry_on_error) else: self.retry = Retry(NoBackoff(), 0) self.health_check_interval = health_check_interval @@ -1052,6 +1070,7 @@ URL_QUERY_ARGUMENT_PARSERS = { "socket_connect_timeout": float, "socket_keepalive": to_bool, "retry_on_timeout": to_bool, + "retry_on_error": list, "max_connections": int, "health_check_interval": int, "ssl_check_hostname": to_bool, diff --git a/redis/retry.py b/redis/retry.py index 75504c7..6147fbd 100644 --- a/redis/retry.py +++ b/redis/retry.py @@ -19,6 +19,14 @@ class Retry: self._retries = retries self._supported_errors = supported_errors + def update_supported_erros(self, specified_errors: list): + """ + Updates the supported errors with the specified error types + """ + self._supported_errors = tuple( + set(self._supported_errors + tuple(specified_errors)) + ) + def call_with_retry(self, do, fail): """ Execute an operation that might fail and returns its result, or |