fix: screener yf.screen() rate limit/401 retry 처리 추가

429/rate limit 및 401/unauthorized 발생 시 최대 3회 재시도 (delay 3s, 6s).
모든 retry 소진 후 RuntimeError로 변환하여 503 응답.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
I Luk Kim 4 months ago
parent fb692fe592
commit 7a003a5360

@ -153,7 +153,34 @@ class ScreenerService:
def _screen_sync(self, query, offset: int, size: int, sort_field: str, sort_asc: bool) -> dict: def _screen_sync(self, query, offset: int, size: int, sort_field: str, sort_asc: bool) -> dict:
"""Synchronous yfinance screen() call — must run in executor.""" """Synchronous yfinance screen() call — must run in executor."""
import yfinance as yf import yfinance as yf
max_retries = 3
for attempt in range(max_retries):
try:
return yf.screen(query, offset=offset, size=size, sortField=sort_field, sortAsc=sort_asc) return yf.screen(query, offset=offset, size=size, sortField=sort_field, sortAsc=sort_asc)
except Exception as e:
err = str(e).lower()
is_retriable = (
"too many requests" in err
or "rate limit" in err
or "429" in err
or "401" in err
or "unauthorized" in err
)
if is_retriable and attempt < max_retries - 1:
delay = (attempt + 1) * 3 # 3s, 6s
logger.warning(
"yfinance screen() error '%s' (attempt %d/%d), retrying in %.1fs",
str(e)[:80], attempt + 1, max_retries, delay,
)
time.sleep(delay)
continue
if is_retriable:
raise RuntimeError(
"Yahoo Finance is rate limiting this server. "
"Please try again in 3060 seconds."
)
raise
async def screen_stocks( async def screen_stocks(
self, self,

Loading…
Cancel
Save