diff --git a/services/trade-monitor/main.py b/services/trade-monitor/main.py new file mode 100644 index 0000000..d0fa302 --- /dev/null +++ b/services/trade-monitor/main.py @@ -0,0 +1,62 @@ +"""trade-monitor FastAPI entry — lifespan(monitor_loop + heartbeat_loop) + /health.""" +from __future__ import annotations + +import asyncio +import logging +from contextlib import asynccontextmanager + +import redis.asyncio as aioredis +from fastapi import FastAPI + +import monitor +from config import load_settings +from kis_client import KISClient +from nas_client import NASClient +from _shared.heartbeat import heartbeat_loop, WorkerStats + +logging.basicConfig(level=logging.INFO, + format="%(asctime)s %(name)s %(levelname)s %(message)s") +logger = logging.getLogger(__name__) + +HEARTBEAT_INTERVAL = 15 # 60초 루프 > TTL 45초 → 독립 15초 발신으로 만료갭 해소 +HEARTBEAT_TTL = 45 + + +@asynccontextmanager +async def lifespan(app: FastAPI): + settings = load_settings() + nas = NASClient(settings.nas_base_url, settings.webai_api_key) + kis = KISClient(settings.kis_app_key, settings.kis_app_secret, + settings.kis_account, settings.kis_is_virtual) + state = monitor.MonitorState() + stats = WorkerStats() + redis = aioredis.from_url(settings.redis_url, decode_responses=False) + + mon_task = asyncio.create_task( + monitor.monitor_loop(nas, kis, state, stats, settings)) + hb_task = asyncio.create_task(heartbeat_loop( + redis, "trade-monitor", "trader", stats, + interval=HEARTBEAT_INTERVAL, ttl=HEARTBEAT_TTL, + state_fn=monitor.make_state_fn(state))) + logger.info("trade-monitor lifespan 시작") + try: + yield + finally: + for t in (mon_task, hb_task): + t.cancel() + try: + await t + except asyncio.CancelledError: + pass + await kis.close() + await nas.close() + await redis.aclose() + logger.info("trade-monitor lifespan 종료") + + +app = FastAPI(lifespan=lifespan) + + +@app.get("/health") +def health(): + return {"ok": True, "service": "trade-monitor"} diff --git a/services/trade-monitor/tests/test_health.py b/services/trade-monitor/tests/test_health.py new file mode 100644 index 0000000..0ec996a --- /dev/null +++ b/services/trade-monitor/tests/test_health.py @@ -0,0 +1,6 @@ +"""/health — 라우트 핸들러 직접 검증.""" +from main import health + + +def test_health(): + assert health() == {"ok": True, "service": "trade-monitor"}