1
+ import abc
1
2
import socket
2
3
from time import sleep
3
- from typing import TYPE_CHECKING , Any , Callable , Iterable , Tuple , Type , TypeVar
4
+ from typing import TYPE_CHECKING , Any , Callable , Generic , Iterable , Tuple , Type , TypeVar
4
5
5
6
from redis .exceptions import ConnectionError , TimeoutError
6
7
7
8
T = TypeVar ("T" )
9
+ E = TypeVar ("E" , bound = Exception , covariant = True )
8
10
9
11
if TYPE_CHECKING :
10
12
from redis .backoff import AbstractBackoff
11
13
12
14
13
- class Retry :
15
+ class AbstractRetry ( Generic [ E ], abc . ABC ) :
14
16
"""Retry a specific number of times after a failure"""
15
17
18
+ _supported_errors : Tuple [Type [E ], ...]
19
+
16
20
def __init__ (
17
21
self ,
18
22
backoff : "AbstractBackoff" ,
19
23
retries : int ,
20
- supported_errors : Tuple [Type [Exception ], ...] = (
21
- ConnectionError ,
22
- TimeoutError ,
23
- socket .timeout ,
24
- ),
24
+ supported_errors : Tuple [Type [E ], ...],
25
25
):
26
26
"""
27
27
Initialize a `Retry` object with a `Backoff` object
@@ -34,22 +34,14 @@ def __init__(
34
34
self ._retries = retries
35
35
self ._supported_errors = supported_errors
36
36
37
+ @abc .abstractmethod
37
38
def __eq__ (self , other : Any ) -> bool :
38
- if not isinstance (other , Retry ):
39
- return NotImplemented
40
-
41
- return (
42
- self ._backoff == other ._backoff
43
- and self ._retries == other ._retries
44
- and set (self ._supported_errors ) == set (other ._supported_errors )
45
- )
39
+ return NotImplemented
46
40
47
41
def __hash__ (self ) -> int :
48
42
return hash ((self ._backoff , self ._retries , frozenset (self ._supported_errors )))
49
43
50
- def update_supported_errors (
51
- self , specified_errors : Iterable [Type [Exception ]]
52
- ) -> None :
44
+ def update_supported_errors (self , specified_errors : Iterable [Type [E ]]) -> None :
53
45
"""
54
46
Updates the supported errors with the specified error types
55
47
"""
@@ -69,6 +61,32 @@ def update_retries(self, value: int) -> None:
69
61
"""
70
62
self ._retries = value
71
63
64
+
65
+ class Retry (AbstractRetry [Exception ]):
66
+ __hash__ = AbstractRetry .__hash__
67
+
68
+ def __init__ (
69
+ self ,
70
+ backoff : "AbstractBackoff" ,
71
+ retries : int ,
72
+ supported_errors : Tuple [Type [Exception ], ...] = (
73
+ ConnectionError ,
74
+ TimeoutError ,
75
+ socket .timeout ,
76
+ ),
77
+ ):
78
+ super ().__init__ (backoff , retries , supported_errors )
79
+
80
+ def __eq__ (self , other : Any ) -> bool :
81
+ if not isinstance (other , Retry ):
82
+ return NotImplemented
83
+
84
+ return (
85
+ self ._backoff == other ._backoff
86
+ and self ._retries == other ._retries
87
+ and set (self ._supported_errors ) == set (other ._supported_errors )
88
+ )
89
+
72
90
def call_with_retry (
73
91
self ,
74
92
do : Callable [[], T ],
0 commit comments