"""스케줄러 단계 타임아웃 가드. 2026-09-22 15:03~16:52: KIS API 무응답으로 데이트레이딩 스케줄러가 1시간 49분 멈춰 15:20 EOD 강제청산을 통째로 건너뜀. 단계마다 타임아웃을 둬 루프가 계속 돌아야 한다. """ import asyncio import pytest from app.services.daytrading import scheduler as sch @pytest.mark.asyncio async def test_guard_returns_value_on_success(): async def ok(): return "done" assert await sch._guard(ok(), "step") == "done" @pytest.mark.asyncio async def test_guard_times_out_and_cancels_hung_step(): cancelled = asyncio.Event() async def hang(): try: await asyncio.sleep(60) except asyncio.CancelledError: cancelled.set() raise result = await sch._guard(hang(), "행 스텝", timeout=0.05) assert result is None await asyncio.sleep(0) # 취소 전파 assert cancelled.is_set(), "타임아웃 시 멈춘 단계는 취소되어야 함" @pytest.mark.asyncio async def test_guard_does_not_swallow_other_errors(): async def boom(): raise RuntimeError("API 오류") with pytest.raises(RuntimeError): await sch._guard(boom(), "step")