-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e3a66b0
commit 233a816
Showing
41 changed files
with
1,558 additions
and
54 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
File renamed without changes.
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,62 @@ | ||
import warnings | ||
import functools | ||
|
||
|
||
def deprecated(reason): | ||
"""This is a decorator which can be used to mark functions as deprecated. | ||
It will result in a warning being emitted when the function is used. | ||
Args: | ||
reason (str): Explanation of why the function is deprecated. | ||
""" | ||
|
||
def decorator(func): | ||
original_func = func.__func__ if isinstance(func, staticmethod) or isinstance(func, classmethod) else func | ||
|
||
@functools.wraps(original_func) | ||
def decorated_function(*args, **kwargs): | ||
warnings.warn(f"Call to deprecated function {original_func.__name__}. {reason}", | ||
category=DeprecationWarning, | ||
stacklevel=2) | ||
return original_func(*args, **kwargs) | ||
|
||
if isinstance(func, staticmethod): | ||
return staticmethod(decorated_function) | ||
elif isinstance(func, classmethod): | ||
return classmethod(decorated_function) | ||
else: | ||
return decorated_function | ||
|
||
return decorator | ||
|
||
|
||
def type_check(*arg_types, **kwarg_types): | ||
"""This decorator is used to check whether the input parameter type meets the definition. | ||
It will result in a warning being emitted when the function is used. | ||
""" | ||
|
||
def decorator(func): | ||
original_func = func.__func__ if isinstance(func, staticmethod) or isinstance(func, classmethod) else func | ||
|
||
@functools.wraps(original_func) | ||
def wrapper(*args, **kwargs): | ||
for i, (a, t) in enumerate(zip(args, arg_types)): | ||
if not isinstance(a, t): | ||
warnings.warn(f"Argument {i} is not of type {t}", | ||
category=UserWarning, | ||
stacklevel=2) | ||
for k, t in kwarg_types.items(): | ||
if k in kwargs and not isinstance(kwargs[k], t): | ||
warnings.warn(f"Argument {k} is not of type {t}", | ||
category=UserWarning, | ||
stacklevel=2) | ||
return original_func(*args, **kwargs) | ||
|
||
if isinstance(func, staticmethod): | ||
return staticmethod(wrapper) | ||
elif isinstance(func, classmethod): | ||
return classmethod(wrapper) | ||
else: | ||
return wrapper | ||
|
||
return decorator |
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from .request import TeaRequest | ||
from darabonba.request import TeaRequest | ||
|
||
|
||
class TeaException(Exception): | ||
|
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
Empty file.
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,73 @@ | ||
import random | ||
from .retry import RetryCondition | ||
|
||
|
||
class BackoffStrategy(object): | ||
|
||
def compute_delay_before_next_retry(self, retry_policy_context): | ||
"""Compute delay for request need to be retried, in milliseconds""" | ||
pass | ||
|
||
|
||
class FixedDelayStrategy(BackoffStrategy): | ||
|
||
def __init__(self, fixed_delay): | ||
self.fixed_delay = fixed_delay | ||
|
||
def compute_delay_before_next_retry(self, retry_policy_context): | ||
return self.fixed_delay | ||
|
||
|
||
class NoDelayStrategy(FixedDelayStrategy): | ||
|
||
def __init__(self): | ||
FixedDelayStrategy.__init__(self, 0) | ||
|
||
|
||
class ExponentialBackoffStrategy(BackoffStrategy): | ||
|
||
MAX_RETRY_LIMIT = 30 # to avoid integer overflow during delay calculation | ||
|
||
def __init__(self, base_delay_in_milliseconds, max_delay_in_milliseconds): | ||
self.base_delay_in_milliseconds = base_delay_in_milliseconds | ||
self.max_delay_in_milliseconds = max_delay_in_milliseconds | ||
|
||
def compute_delay_before_next_retry(self, retry_policy_context): | ||
retries = min(self.MAX_RETRY_LIMIT, retry_policy_context.retries_attempted) | ||
delay = min(self.max_delay_in_milliseconds, self.base_delay_in_milliseconds << retries) | ||
return delay | ||
|
||
|
||
class JitteredExponentialBackoffStrategy(ExponentialBackoffStrategy): | ||
|
||
def compute_delay_before_next_retry(self, retry_policy_context): | ||
delay = ExponentialBackoffStrategy.compute_delay_before_next_retry(self, | ||
retry_policy_context) | ||
return delay / 2 + random.randint(0, int(delay / 2)) | ||
|
||
|
||
class DefaultMixedBackoffStrategy(BackoffStrategy): | ||
|
||
# in milliseconds | ||
SDK_DEFAULT_BASE_DELAY = 100 | ||
SDK_DEFAULT_TROTTLED_BASE_DELAY = 500 | ||
SDK_DEFAULT_MAX_BACKOFF = 20 * 1000 | ||
|
||
def __init__(self): | ||
self._default_backoff_strategy = ExponentialBackoffStrategy( | ||
self.SDK_DEFAULT_BASE_DELAY, | ||
self.SDK_DEFAULT_MAX_BACKOFF | ||
) | ||
self._default_throttled_backoff_strategy = JitteredExponentialBackoffStrategy( | ||
self.SDK_DEFAULT_TROTTLED_BASE_DELAY, | ||
self.SDK_DEFAULT_MAX_BACKOFF | ||
) | ||
|
||
def compute_delay_before_next_retry(self, retry_policy_context): | ||
retryable = retry_policy_context.retryable | ||
if retryable & RetryCondition.SHOULD_RETRY_WITH_THROTTLING_BACKOFF: | ||
return self._default_throttled_backoff_strategy.compute_delay_before_next_retry( | ||
retry_policy_context) | ||
else: | ||
return self._default_backoff_strategy.compute_delay_before_next_retry( | ||
retry_policy_context) |
Oops, something went wrong.