Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/redis/asyncio/retry.py: 37%

27 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-23 06:16 +0000

1from asyncio import sleep 

2from typing import TYPE_CHECKING, Any, Awaitable, Callable, Tuple, Type, TypeVar 

3 

4from redis.exceptions import ConnectionError, RedisError, TimeoutError 

5 

6if TYPE_CHECKING: 

7 from redis.backoff import AbstractBackoff 

8 

9 

10T = TypeVar("T") 

11 

12 

13class Retry: 

14 """Retry a specific number of times after a failure""" 

15 

16 __slots__ = "_backoff", "_retries", "_supported_errors" 

17 

18 def __init__( 

19 self, 

20 backoff: "AbstractBackoff", 

21 retries: int, 

22 supported_errors: Tuple[Type[RedisError], ...] = ( 

23 ConnectionError, 

24 TimeoutError, 

25 ), 

26 ): 

27 """ 

28 Initialize a `Retry` object with a `Backoff` object 

29 that retries a maximum of `retries` times. 

30 `retries` can be negative to retry forever. 

31 You can specify the types of supported errors which trigger 

32 a retry with the `supported_errors` parameter. 

33 """ 

34 self._backoff = backoff 

35 self._retries = retries 

36 self._supported_errors = supported_errors 

37 

38 def update_supported_errors(self, specified_errors: list): 

39 """ 

40 Updates the supported errors with the specified error types 

41 """ 

42 self._supported_errors = tuple( 

43 set(self._supported_errors + tuple(specified_errors)) 

44 ) 

45 

46 async def call_with_retry( 

47 self, do: Callable[[], Awaitable[T]], fail: Callable[[RedisError], Any] 

48 ) -> T: 

49 """ 

50 Execute an operation that might fail and returns its result, or 

51 raise the exception that was thrown depending on the `Backoff` object. 

52 `do`: the operation to call. Expects no argument. 

53 `fail`: the failure handler, expects the last error that was thrown 

54 """ 

55 self._backoff.reset() 

56 failures = 0 

57 while True: 

58 try: 

59 return await do() 

60 except self._supported_errors as error: 

61 failures += 1 

62 await fail(error) 

63 if self._retries >= 0 and failures > self._retries: 

64 raise error 

65 backoff = self._backoff.compute(failures) 

66 if backoff > 0: 

67 await sleep(backoff)