From aa3c1a953aa6c66c3c82dff5d489988a41d8d97a Mon Sep 17 00:00:00 2001 From: enenn Date: Sat, 24 Mar 2018 08:46:20 +0100 Subject: [PATCH] Add retrier decorator --- freqtrade/exchange/__init__.py | 21 ++++++++++++++++++++- freqtrade/tests/exchange/test_exchange.py | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 5070e89b2..9a7cd08a5 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -16,6 +16,7 @@ logger = logging.getLogger(__name__) # Current selected exchange _API: ccxt.Exchange = None _CONF: dict = {} +API_RETRY_COUNT = 4 # Holds all open sell orders for dry_run _DRY_RUN_OPEN_ORDERS: Dict[str, Any] = {} @@ -23,6 +24,23 @@ _DRY_RUN_OPEN_ORDERS: Dict[str, Any] = {} _TICKER_CACHE: dict = {} +def retrier(f): + def wrapper(*args, **kwargs): + count = kwargs.pop('count', API_RETRY_COUNT) + try: + return f(*args, **kwargs) + except (NetworkException, DependencyException) as ex: + logger.warning('%s returned exception: "%s"', f, ex) + if count > 0: + count -= 1 + kwargs.update({'count': count}) + logger.warning('retrying %s still for %s times', f, count) + return wrapper(*args, **kwargs) + else: + raise OperationalException('Giving up retrying: %s', f) + return wrapper + + def init(config: dict) -> None: """ Initializes this module with the given config, @@ -192,6 +210,7 @@ def get_balances() -> dict: raise OperationalException(e) +@retrier def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict: global _TICKER_CACHE try: @@ -208,7 +227,7 @@ def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict: raise OperationalException(e) -@cached(TTLCache(maxsize=100, ttl=30)) +@retrier def get_ticker_history(pair: str, tick_interval: str) -> List[Dict]: if 'fetchOHLCV' not in _API.has or not _API.has['fetchOHLCV']: raise OperationalException( diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index eacc641d5..8805cfab3 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -307,7 +307,7 @@ def test_get_ticker(default_conf, mocker): assert ticker['bid'] == 0.5 assert ticker['ask'] == 1 - with pytest.raises(NetworkException): + with pytest.raises(OperationalException): # test retrier api_mock.fetch_ticker = MagicMock(side_effect=ccxt.NetworkError) mocker.patch('freqtrade.exchange._API', api_mock) get_ticker(pair='ETH/BTC', refresh=True) @@ -365,7 +365,7 @@ def test_get_ticker_history(default_conf, mocker): assert ticks[0]['C'] == 4 assert ticks[0]['V'] == 5 - with pytest.raises(NetworkException): + with pytest.raises(OperationalException): # test retrier api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.NetworkError) mocker.patch('freqtrade.exchange._API', api_mock) # new symbol to get around cache