fix: add 30s timeout to get_bars to prevent silent hang on 200-bar fetch
This commit is contained in:
+13
-1
@@ -1,12 +1,15 @@
|
|||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import backoff
|
import backoff
|
||||||
|
import concurrent.futures
|
||||||
import alpaca_trade_api as tradeapi
|
import alpaca_trade_api as tradeapi
|
||||||
import requests.exceptions
|
import requests.exceptions
|
||||||
|
|
||||||
logging.getLogger('backoff').setLevel(logging.CRITICAL)
|
logging.getLogger('backoff').setLevel(logging.CRITICAL)
|
||||||
|
|
||||||
_RETRYABLE_ERRORS = (tradeapi.rest.APIError, ConnectionError, requests.exceptions.ConnectionError)
|
BARS_REQUEST_TIMEOUT = 30
|
||||||
|
|
||||||
|
_RETRYABLE_ERRORS = (tradeapi.rest.APIError, ConnectionError, requests.exceptions.ConnectionError, requests.exceptions.Timeout, TimeoutError)
|
||||||
|
|
||||||
|
|
||||||
def _is_position_not_found(e):
|
def _is_position_not_found(e):
|
||||||
@@ -27,11 +30,20 @@ class AlpacaClient:
|
|||||||
|
|
||||||
@backoff.on_exception(backoff.expo, _RETRYABLE_ERRORS, max_tries=5, jitter=backoff.full_jitter)
|
@backoff.on_exception(backoff.expo, _RETRYABLE_ERRORS, max_tries=5, jitter=backoff.full_jitter)
|
||||||
def get_bars(self, symbol, timeframe, **kwargs):
|
def get_bars(self, symbol, timeframe, **kwargs):
|
||||||
|
def _fetch():
|
||||||
bars = self.api.get_bars(symbol, timeframe, **kwargs)
|
bars = self.api.get_bars(symbol, timeframe, **kwargs)
|
||||||
if bars is None:
|
if bars is None:
|
||||||
return None
|
return None
|
||||||
return bars.df
|
return bars.df
|
||||||
|
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
|
||||||
|
future = executor.submit(_fetch)
|
||||||
|
try:
|
||||||
|
return future.result(timeout=BARS_REQUEST_TIMEOUT)
|
||||||
|
except concurrent.futures.TimeoutError:
|
||||||
|
logging.warning(f"get_bars timed out after {BARS_REQUEST_TIMEOUT}s for {symbol} {timeframe}")
|
||||||
|
raise TimeoutError(f"get_bars hung for {symbol} {timeframe}")
|
||||||
|
|
||||||
@backoff.on_exception(backoff.expo, _RETRYABLE_ERRORS, max_tries=5, jitter=backoff.full_jitter)
|
@backoff.on_exception(backoff.expo, _RETRYABLE_ERRORS, max_tries=5, jitter=backoff.full_jitter)
|
||||||
def get_latest_quote(self, symbol):
|
def get_latest_quote(self, symbol):
|
||||||
return self.api.get_latest_quote(symbol)
|
return self.api.get_latest_quote(symbol)
|
||||||
|
|||||||
Reference in New Issue
Block a user