Retries the specified function with a simple exponential backoff algorithm. This is necessary when AWS is not yet ready to perform an action because all resources have not been fully deployed. :param func: The function to retry. :param error_code: The error
(self, *func_args, **func_kwargs)
| 39 | self.max_sleep = max_sleep |
| 40 | |
| 41 | def run(self, *func_args, **func_kwargs): |
| 42 | """ |
| 43 | Retries the specified function with a simple exponential backoff algorithm. |
| 44 | This is necessary when AWS is not yet ready to perform an action because all |
| 45 | resources have not been fully deployed. |
| 46 | |
| 47 | :param func: The function to retry. |
| 48 | :param error_code: The error code to retry. Other errors are raised again. |
| 49 | :param func_args: The positional arguments to pass to the function. |
| 50 | :param func_kwargs: The keyword arguments to pass to the function. |
| 51 | :return: The return value of the retried function. |
| 52 | """ |
| 53 | sleepy_time = 1 |
| 54 | func_return = None |
| 55 | while sleepy_time <= self.max_sleep and func_return is None: |
| 56 | try: |
| 57 | func_return = self.func(*func_args, **func_kwargs) |
| 58 | logger.info("Ran %s, got %s.", self.func.__name__, func_return) |
| 59 | except ClientError as error: |
| 60 | if error.response["Error"]["Code"] == self.error_code: |
| 61 | print( |
| 62 | f"Sleeping for {sleepy_time} to give AWS time to " |
| 63 | f"connect resources." |
| 64 | ) |
| 65 | time.sleep(sleepy_time) |
| 66 | sleepy_time = sleepy_time * 2 |
| 67 | else: |
| 68 | logger.error( |
| 69 | "%s raised an error and cannot be retried.", self.func.__name__ |
| 70 | ) |
| 71 | raise |
| 72 | if sleepy_time > self.max_sleep: |
| 73 | raise MaxRetriesExceededError( |
| 74 | f"{self.func.__name__} exceeded the allowable number of retries." |
| 75 | ) |
| 76 | return func_return |