Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/redis/backoff.py: 53%

51 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 07:16 +0000

1import random 

2from abc import ABC, abstractmethod 

3 

4# Maximum backoff between each retry in seconds 

5DEFAULT_CAP = 0.512 

6# Minimum backoff between each retry in seconds 

7DEFAULT_BASE = 0.008 

8 

9 

10class AbstractBackoff(ABC): 

11 """Backoff interface""" 

12 

13 def reset(self): 

14 """ 

15 Reset internal state before an operation. 

16 `reset` is called once at the beginning of 

17 every call to `Retry.call_with_retry` 

18 """ 

19 pass 

20 

21 @abstractmethod 

22 def compute(self, failures): 

23 """Compute backoff in seconds upon failure""" 

24 pass 

25 

26 

27class ConstantBackoff(AbstractBackoff): 

28 """Constant backoff upon failure""" 

29 

30 def __init__(self, backoff): 

31 """`backoff`: backoff time in seconds""" 

32 self._backoff = backoff 

33 

34 def compute(self, failures): 

35 return self._backoff 

36 

37 

38class NoBackoff(ConstantBackoff): 

39 """No backoff upon failure""" 

40 

41 def __init__(self): 

42 super().__init__(0) 

43 

44 

45class ExponentialBackoff(AbstractBackoff): 

46 """Exponential backoff upon failure""" 

47 

48 def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): 

49 """ 

50 `cap`: maximum backoff time in seconds 

51 `base`: base backoff time in seconds 

52 """ 

53 self._cap = cap 

54 self._base = base 

55 

56 def compute(self, failures): 

57 return min(self._cap, self._base * 2**failures) 

58 

59 

60class FullJitterBackoff(AbstractBackoff): 

61 """Full jitter backoff upon failure""" 

62 

63 def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): 

64 """ 

65 `cap`: maximum backoff time in seconds 

66 `base`: base backoff time in seconds 

67 """ 

68 self._cap = cap 

69 self._base = base 

70 

71 def compute(self, failures): 

72 return random.uniform(0, min(self._cap, self._base * 2**failures)) 

73 

74 

75class EqualJitterBackoff(AbstractBackoff): 

76 """Equal jitter backoff upon failure""" 

77 

78 def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): 

79 """ 

80 `cap`: maximum backoff time in seconds 

81 `base`: base backoff time in seconds 

82 """ 

83 self._cap = cap 

84 self._base = base 

85 

86 def compute(self, failures): 

87 temp = min(self._cap, self._base * 2**failures) / 2 

88 return temp + random.uniform(0, temp) 

89 

90 

91class DecorrelatedJitterBackoff(AbstractBackoff): 

92 """Decorrelated jitter backoff upon failure""" 

93 

94 def __init__(self, cap=DEFAULT_CAP, base=DEFAULT_BASE): 

95 """ 

96 `cap`: maximum backoff time in seconds 

97 `base`: base backoff time in seconds 

98 """ 

99 self._cap = cap 

100 self._base = base 

101 self._previous_backoff = 0 

102 

103 def reset(self): 

104 self._previous_backoff = 0 

105 

106 def compute(self, failures): 

107 max_backoff = max(self._base, self._previous_backoff * 3) 

108 temp = random.uniform(self._base, max_backoff) 

109 self._previous_backoff = min(self._cap, temp) 

110 return self._previous_backoff 

111 

112 

113def default_backoff(): 

114 return EqualJitterBackoff()