refactor: Alpaca intraday 120초 타임아웃 + limit-concurrency 50 복원

asyncio.wait_for로 120초 타임아웃 명시, _do_fetch 내부 함수로 semaphore 래핑.
limit-concurrency를 20→50으로 복원 (세마포어 5개로 충분히 제어됨).

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

@ -128,26 +128,37 @@ async def get_alpaca_intraday_multi(
start_dt = datetime.combine(_start, datetime.min.time()).replace(tzinfo=timezone.utc) start_dt = datetime.combine(_start, datetime.min.time()).replace(tzinfo=timezone.utc)
end_dt = datetime.combine(_end, datetime.max.time()).replace(tzinfo=timezone.utc) end_dt = datetime.combine(_end, datetime.max.time()).replace(tzinfo=timezone.utc)
async with _INTRADAY_SEMAPHORE: async def _do_fetch():
try: async with _INTRADAY_SEMAPHORE:
data = await svc.get_or_fetch_multi_bars( try:
symbols, start_dt, end_dt, interval, force_refresh, feed="sip" return await svc.get_or_fetch_multi_bars(
) symbols, start_dt, end_dt, interval, force_refresh, feed="sip"
except Exception as e:
err = str(e)
detail = f"Alpaca API error: {err}"
if "502" in err or "Bad Gateway" in err:
detail = (
f"Alpaca 502 Bad Gateway — 요청당 심볼 수 초과 가능성. "
f"내부 배치 크기: 100개/요청. 원인: {err}"
) )
raise HTTPException(status_code=502, detail=detail) finally:
finally: try:
await svc.client.close() await svc.client.close()
except Exception:
pass
try:
data = await asyncio.wait_for(_do_fetch(), timeout=120)
except asyncio.TimeoutError:
raise HTTPException(
status_code=504,
detail="요청 시간 초과 (120초). 티커 수를 줄이거나 나중에 다시 시도하세요.",
)
except HTTPException:
raise
except Exception as e:
err = str(e)
detail = f"Alpaca API error: {err}"
if "502" in err or "Bad Gateway" in err:
detail = (
f"Alpaca 502 Bad Gateway — 요청당 심볼 수 초과 가능성. "
f"내부 배치 크기: 100개/요청. 원인: {err}"
)
raise HTTPException(status_code=502, detail=detail)
# Reclaim Alpaca HTTP buffers, intermediate bar dicts, and DB row objects
# before building the serialised response. Prevents Python heap from growing
# unboundedly across thousands of backfill requests in a long-running worker.
gc.collect() gc.collect()
bars = { bars = {
@ -207,22 +218,36 @@ async def get_alpaca_intraday_today(
start_dt = datetime.combine(today, datetime.min.time()).replace(tzinfo=timezone.utc) start_dt = datetime.combine(today, datetime.min.time()).replace(tzinfo=timezone.utc)
end_dt = datetime.combine(today, datetime.max.time()).replace(tzinfo=timezone.utc) end_dt = datetime.combine(today, datetime.max.time()).replace(tzinfo=timezone.utc)
async with _INTRADAY_SEMAPHORE: async def _do_fetch():
try: async with _INTRADAY_SEMAPHORE:
data = await svc.get_or_fetch_multi_bars( try:
symbols, start_dt, end_dt, interval, force_refresh=True, feed="iex" return await svc.get_or_fetch_multi_bars(
) symbols, start_dt, end_dt, interval, force_refresh=True, feed="iex"
except Exception as e:
err = str(e)
detail = f"Alpaca API error: {err}"
if "502" in err or "Bad Gateway" in err:
detail = (
f"Alpaca 502 Bad Gateway — 요청당 심볼 수 초과 가능성. "
f"내부 배치 크기: 100개/요청. 원인: {err}"
) )
raise HTTPException(status_code=502, detail=detail) finally:
finally: try:
await svc.client.close() await svc.client.close()
except Exception:
pass
try:
data = await asyncio.wait_for(_do_fetch(), timeout=120)
except asyncio.TimeoutError:
raise HTTPException(
status_code=504,
detail="요청 시간 초과 (120초). 티커 수를 줄이거나 나중에 다시 시도하세요.",
)
except HTTPException:
raise
except Exception as e:
err = str(e)
detail = f"Alpaca API error: {err}"
if "502" in err or "Bad Gateway" in err:
detail = (
f"Alpaca 502 Bad Gateway — 요청당 심볼 수 초과 가능성. "
f"내부 배치 크기: 100개/요청. 원인: {err}"
)
raise HTTPException(status_code=502, detail=detail)
gc.collect() gc.collect()

@ -68,7 +68,7 @@ services:
mem_limit: 2g mem_limit: 2g
memswap_limit: 2g memswap_limit: 2g
restart: unless-stopped restart: unless-stopped
command: ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "18000", "--reload", "--limit-concurrency", "20"] command: ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "18000", "--reload", "--limit-concurrency", "50"]
# Frontend Application # Frontend Application
frontend: frontend:

Loading…
Cancel
Save