fix: 서버 응답불능 — limit-concurrency 20 + asyncio yield points

BaseHTTPMiddleware는 요청당 2개 asyncio task를 생성한다.
--limit-concurrency 100은 여전히 200개 task가 event loop를 포화시켜
health check 포함 모든 요청이 block됐다.

변경 사항:
- docker-compose.yml: --limit-concurrency 100 → 20
  (세마포어 10개 처리 + 10개 대기, 나머지 20초과 시 503으로 즉시 반환)
- alpaca_price_service.py: upsert 루프 청크 사이 + Phase 4 ORM 일괄 생성 후
  await asyncio.sleep(0) 추가 — 동기 CPU 블로킹 중 event loop yield 보장

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

@ -2,6 +2,7 @@
Alpaca bars AlpacaPriceData conversion and DB storage
"""
import asyncio
import logging
from datetime import datetime, timezone
from typing import Dict, List, Optional
@ -84,6 +85,7 @@ class AlpacaPriceService:
stmt = stmt.on_conflict_do_nothing(constraint='uq_alpaca_price_data')
result = await db.execute(stmt)
inserted += result.rowcount
await asyncio.sleep(0) # yield event loop between chunks
await db.commit()
if inserted:
@ -183,6 +185,7 @@ class AlpacaPriceService:
stmt = pg_insert(AlpacaPriceData).values(rows[i : i + CHUNK])
stmt = stmt.on_conflict_do_nothing(constraint="uq_alpaca_price_data")
await db.execute(stmt)
await asyncio.sleep(0) # yield event loop between chunks
await db.commit()
logger.info(
f"Alpaca multi-bars: stored {len(rows)} rows for {len(need_fetch)} tickers"
@ -203,6 +206,7 @@ class AlpacaPriceService:
.order_by(AlpacaPriceData.ticker, AlpacaPriceData.date)
)
db_rows = result.scalars().all()
await asyncio.sleep(0) # yield after bulk ORM object creation
data: Dict[str, List[AlpacaPriceData]] = {t: [] for t in upper_tickers}
for row in db_rows:

@ -66,7 +66,7 @@ services:
- ./yfinance_plus:/app/yfinance_plus # Mount yfinance_plus for development
- ./data:/app/data # For data files
restart: unless-stopped
command: ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "18000", "--reload", "--limit-concurrency", "100"]
command: ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "18000", "--reload", "--limit-concurrency", "20"]
# Frontend Application
frontend:

Loading…
Cancel
Save