1# Copyright 2020 gRPC authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""This contains common retrying helpers (retryers). 15 16We use tenacity as a general-purpose retrying library. 17 18> It [tenacity] originates from a fork of retrying which is sadly no 19> longer maintained. Tenacity isn’t api compatible with retrying but > 20> adds significant new functionality and fixes a number of longstanding bugs. 21> - https://tenacity.readthedocs.io/en/latest/index.html 22""" 23import datetime 24from typing import Any, List, Optional 25 26import tenacity 27 28# Type aliases 29timedelta = datetime.timedelta 30Retrying = tenacity.Retrying 31_retry_if_exception_type = tenacity.retry_if_exception_type 32_stop_after_delay = tenacity.stop_after_delay 33_wait_exponential = tenacity.wait_exponential 34 35 36def _retry_on_exceptions(retry_on_exceptions: Optional[List[Any]] = None): 37 # Retry on all exceptions by default 38 if retry_on_exceptions is None: 39 retry_on_exceptions = (Exception,) 40 return _retry_if_exception_type(retry_on_exceptions) 41 42 43def exponential_retryer_with_timeout( 44 *, 45 wait_min: timedelta, 46 wait_max: timedelta, 47 timeout: timedelta, 48 retry_on_exceptions: Optional[List[Any]] = None) -> Retrying: 49 return Retrying(retry=_retry_on_exceptions(retry_on_exceptions), 50 wait=_wait_exponential(min=wait_min.total_seconds(), 51 max=wait_max.total_seconds()), 52 stop=_stop_after_delay(timeout.total_seconds()), 53 reraise=True) 54