Dynamic backoff on DDos errors
This commit is contained in:
		| @@ -91,6 +91,13 @@ MAP_EXCHANGE_CHILDCLASS = { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def calculate_backoff(retry, max_retries): | ||||||
|  |     """ | ||||||
|  |     Calculate backoff | ||||||
|  |     """ | ||||||
|  |     return retry ** 2 + 1 | ||||||
|  |  | ||||||
|  |  | ||||||
| def retrier_async(f): | def retrier_async(f): | ||||||
|     async def wrapper(*args, **kwargs): |     async def wrapper(*args, **kwargs): | ||||||
|         count = kwargs.pop('count', API_RETRY_COUNT) |         count = kwargs.pop('count', API_RETRY_COUNT) | ||||||
| @@ -125,13 +132,13 @@ def retrier(_func=None, retries=API_RETRY_COUNT): | |||||||
|                     kwargs.update({'count': count}) |                     kwargs.update({'count': count}) | ||||||
|                     logger.warning('retrying %s() still for %s times', f.__name__, count) |                     logger.warning('retrying %s() still for %s times', f.__name__, count) | ||||||
|                     if isinstance(ex, DDosProtection): |                     if isinstance(ex, DDosProtection): | ||||||
|                         time.sleep(1) |                         time.sleep(calculate_backoff(count, retries)) | ||||||
|                     return wrapper(*args, **kwargs) |                     return wrapper(*args, **kwargs) | ||||||
|                 else: |                 else: | ||||||
|                     logger.warning('Giving up retrying: %s()', f.__name__) |                     logger.warning('Giving up retrying: %s()', f.__name__) | ||||||
|                     raise ex |                     raise ex | ||||||
|         return wrapper |         return wrapper | ||||||
|     # Support both @retrier and @retrier() syntax |     # Support both @retrier and @retrier(retries=2) syntax | ||||||
|     if _func is None: |     if _func is None: | ||||||
|         return decorator |         return decorator | ||||||
|     else: |     else: | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ from pandas import DataFrame | |||||||
| from freqtrade.exceptions import (DependencyException, InvalidOrderException, DDosProtection, | from freqtrade.exceptions import (DependencyException, InvalidOrderException, DDosProtection, | ||||||
|                                   OperationalException, TemporaryError) |                                   OperationalException, TemporaryError) | ||||||
| from freqtrade.exchange import Binance, Exchange, Kraken | from freqtrade.exchange import Binance, Exchange, Kraken | ||||||
| from freqtrade.exchange.common import API_RETRY_COUNT | from freqtrade.exchange.common import API_RETRY_COUNT, calculate_backoff | ||||||
| from freqtrade.exchange.exchange import (market_is_active, symbol_is_pair, | from freqtrade.exchange.exchange import (market_is_active, symbol_is_pair, | ||||||
|                                          timeframe_to_minutes, |                                          timeframe_to_minutes, | ||||||
|                                          timeframe_to_msecs, |                                          timeframe_to_msecs, | ||||||
| @@ -2296,3 +2296,15 @@ def test_calculate_fee_rate(mocker, default_conf, order, expected) -> None: | |||||||
|  |  | ||||||
|     ex = get_patched_exchange(mocker, default_conf) |     ex = get_patched_exchange(mocker, default_conf) | ||||||
|     assert ex.calculate_fee_rate(order) == expected |     assert ex.calculate_fee_rate(order) == expected | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pytest.mark.parametrize('retry,max_retries,expected', [ | ||||||
|  |     (0, 3, 1), | ||||||
|  |     (1, 3, 2), | ||||||
|  |     (2, 3, 5), | ||||||
|  |     (3, 3, 10), | ||||||
|  |     (0, 1, 1), | ||||||
|  |     (1, 1, 2), | ||||||
|  | ]) | ||||||
|  | def test_calculate_backoff(retry, max_retries, expected): | ||||||
|  |     assert calculate_backoff(retry, max_retries) == expected | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user