diff --git a/dnacentersdk/api/__init__.py b/dnacentersdk/api/__init__.py index e00e4fc7..85119e10 100644 --- a/dnacentersdk/api/__init__.py +++ b/dnacentersdk/api/__init__.py @@ -30,6 +30,7 @@ DEFAULT_BASE_URL, DEFAULT_SINGLE_REQUEST_TIMEOUT, DEFAULT_WAIT_ON_RATE_LIMIT, + DEFAULT_MAX_RETRIES_ON_RATE_LIMIT, DEFAULT_VERIFY, ) import dnacentersdk.environment as dnacenter_environment @@ -654,6 +655,7 @@ def __init__(self, username=None, base_url=None, single_request_timeout=None, wait_on_rate_limit=None, + max_retries_on_rate_limit=None, verify=None, version=None, debug=None, @@ -700,6 +702,11 @@ def __init__(self, username=None, environment variable or dnacentersdk.config.DEFAULT_WAIT_ON_RATE_LIMIT if the environment variable is not set. + max_retries_on_rate_limit(int): Maximum number of request retries + performed by automatic rate-limit handling Defaults to the + DNA_CENTER_MAX_RETRIES_ON_RATE_LIMIT environment variable or + dnacentersdk.config.DEFAULT_MAX_RETRIES_ON_RATE_LIMIT + if the environment variable is not set. verify(bool,basestring): Controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to the DNA_CENTER_VERIFY @@ -745,8 +752,12 @@ def __init__(self, username=None, if wait_on_rate_limit is None: wait_on_rate_limit = dnacenter_environment.get_env_wait_on_rate_limit() or DEFAULT_WAIT_ON_RATE_LIMIT + if max_retries_on_rate_limit is None: + max_retries_on_rate_limit = dnacenter_environment.get_env_max_retries_on_rate_limit() \ + if dnacenter_environment.get_env_max_retries_on_rate_limit() is not None else DEFAULT_MAX_RETRIES_ON_RATE_LIMIT + if verify is None: - verify = dnacenter_environment.get_env_verify() if dnacenter_environment.get_env_verify() != None else DEFAULT_VERIFY + verify = dnacenter_environment.get_env_verify() if dnacenter_environment.get_env_verify() is not None else DEFAULT_VERIFY version = version or dnacenter_environment.get_env_version() or DEFAULT_VERSION @@ -813,6 +824,7 @@ def get_access_token(): base_url=base_url, single_request_timeout=single_request_timeout, wait_on_rate_limit=wait_on_rate_limit, + max_retries_on_rate_limit=max_retries_on_rate_limit, verify=verify, version=version, debug=debug, diff --git a/dnacentersdk/config.py b/dnacentersdk/config.py index 09da898e..ef9cd419 100644 --- a/dnacentersdk/config.py +++ b/dnacentersdk/config.py @@ -40,6 +40,10 @@ #: Enables or disables automatic rate-limit handling. DEFAULT_WAIT_ON_RATE_LIMIT = True +#: **retries_on_rate_limit** default value. +#: Maximum number of times automatic rate-limit handling retries requests. +DEFAULT_MAX_RETRIES_ON_RATE_LIMIT = 5 + #: **verify** default value. #: Controls whether to verify the server's TLS certificate or not. DEFAULT_VERIFY = True diff --git a/dnacentersdk/environment.py b/dnacentersdk/environment.py index b7d48375..c7cdbf05 100644 --- a/dnacentersdk/environment.py +++ b/dnacentersdk/environment.py @@ -50,6 +50,9 @@ #: name of the environment wait_on_rate_limit variable WAIT_ON_RATE_LIMIT_ENVIRONMENT_VARIABLE = 'DNA_CENTER_WAIT_ON_RATE_LIMIT' +#: name of the environment max_retries_on_rate_limit variable +MAX_RETRIES_ON_RATE_LIMIT_ENVIRONMENT_VARIABLE = 'DNA_CENTER_MAX_RETRIES_ON_RATE_LIMIT' + #: name of the environment verify variable VERIFY_ENVIRONMENT_VARIABLE = 'DNA_CENTER_VERIFY' @@ -120,6 +123,13 @@ def get_env_wait_on_rate_limit(): return DNA_CENTER_WAIT_ON_RATE_LIMIT +def get_env_max_retries_on_rate_limit(): + DNA_CENTER_MAX_RETRIES_ON_RATE_LIMIT = _get_env_value( + MAX_RETRIES_ON_RATE_LIMIT_ENVIRONMENT_VARIABLE, + int, int) + return DNA_CENTER_MAX_RETRIES_ON_RATE_LIMIT + + def get_env_verify(): DNA_CENTER_VERIFY = _get_env_value(VERIFY_ENVIRONMENT_VARIABLE, bool, _is_bool) return DNA_CENTER_VERIFY diff --git a/dnacentersdk/restsession.py b/dnacentersdk/restsession.py index bfaa5805..a3cac452 100644 --- a/dnacentersdk/restsession.py +++ b/dnacentersdk/restsession.py @@ -47,6 +47,7 @@ DEFAULT_SINGLE_REQUEST_TIMEOUT, DEFAULT_VERIFY, DEFAULT_WAIT_ON_RATE_LIMIT, + DEFAULT_MAX_RETRIES_ON_RATE_LIMIT, ) from .exceptions import ( ApiError, @@ -140,6 +141,7 @@ class RestSession(object): def __init__(self, get_access_token, access_token, base_url, single_request_timeout=DEFAULT_SINGLE_REQUEST_TIMEOUT, wait_on_rate_limit=DEFAULT_WAIT_ON_RATE_LIMIT, + max_retries_on_rate_limit=DEFAULT_MAX_RETRIES_ON_RATE_LIMIT, verify=DEFAULT_VERIFY, version=None, debug=False): @@ -156,6 +158,8 @@ def __init__(self, get_access_token, access_token, base_url, HTTP REST API request. wait_on_rate_limit(bool): Enable or disable automatic rate-limit handling. + max_retries_on_rate_limit(int): Maximum number of request retries + performed by automatic rate-limit handling verify(bool,basestring): Controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use. @@ -186,6 +190,7 @@ def __init__(self, get_access_token, access_token, base_url, self._access_token = str(access_token) self._single_request_timeout = single_request_timeout self._wait_on_rate_limit = wait_on_rate_limit + self._max_retries_on_rate_limit = max_retries_on_rate_limit self._verify = verify self._version = version self._debug = debug @@ -436,6 +441,7 @@ def request(self, method, url, erc, custom_refresh, **kwargs): kwargs.pop('data', None) c = custom_refresh + rate_limit_retry = 0 while True: c += 1 # Make the HTTP request to the API endpoint @@ -454,26 +460,15 @@ def request(self, method, url, erc, custom_refresh, **kwargs): **kwargs) except Exception as e: raise dnacentersdkException('Socket error {}'.format(e)) - except IOError as e: - if e.errno == errno.EPIPE: - # EPIPE error - try: - c += 1 - logger.debug('Attempt {}'.format(c)) - response = self._req_session.request(method, abs_url, - **kwargs) - except Exception as e: - raise dnacentersdkException('PipeError {}'.format(e)) - else: - raise dnacentersdkException('IOError {}'.format(e)) try: # Check the response code for error conditions check_response_code(response, erc) except RateLimitError as e: # Catch rate-limit errors # Wait and retry if automatic rate-limit handling is enabled - if self.wait_on_rate_limit: - warnings.warn(RateLimitWarning(response)) + if self.wait_on_rate_limit and rate_limit_retry < self._max_retries_on_rate_limit: + logger.warning(RateLimitWarning(response)) + rate_limit_retry += 1 time.sleep(e.retry_after) continue else: