-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enhance(client): add http_retry decorator (#1104)
add http_retry decorator
- Loading branch information
1 parent
2c2c2df
commit cbd0602
Showing
6 changed files
with
140 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import typing as t | ||
from inspect import iscoroutinefunction | ||
from urllib.error import HTTPError | ||
|
||
import requests | ||
from tenacity import Retrying | ||
from tenacity.stop import stop_after_attempt | ||
from tenacity.retry import retry_if_exception | ||
from tenacity._asyncio import AsyncRetrying | ||
from requests.exceptions import HTTPError as RequestsHTTPError | ||
|
||
# https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines | ||
_RETRY_HTTP_STATUS_CODES = (408, 429, 500, 502, 503, 504) | ||
|
||
|
||
class retry_if_http_exception(retry_if_exception): | ||
def __init__(self, status_codes: t.Optional[t.Sequence[int]] = None) -> None: | ||
self.status_codes = status_codes or _RETRY_HTTP_STATUS_CODES | ||
|
||
def _predicate(e: BaseException) -> bool: | ||
if isinstance(e, RequestsHTTPError) and isinstance( | ||
e.response, requests.Response | ||
): | ||
return e.response.status_code in self.status_codes | ||
elif isinstance(e, HTTPError): | ||
return e.code in self.status_codes | ||
else: | ||
return False | ||
|
||
super().__init__(_predicate) | ||
|
||
|
||
def http_retry(*args: t.Any, **kw: t.Any) -> t.Any: | ||
|
||
# support http_retry and http_retry() | ||
if len(args) == 1 and callable(args[0]): | ||
return http_retry()(args[0]) | ||
else: | ||
|
||
def wrap(f: t.Callable) -> t.Any: | ||
_attempts = kw.get("attempts", 3) | ||
_cls = AsyncRetrying if iscoroutinefunction(f) else Retrying | ||
return _cls( | ||
*args, | ||
reraise=True, | ||
stop=stop_after_attempt(_attempts), | ||
retry=retry_if_http_exception(_RETRY_HTTP_STATUS_CODES), | ||
).wraps(f) | ||
|
||
return wrap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters