import asyncio from datetime import datetime, timedelta from zoneinfo import ZoneInfo from app.crud import visit as visit_crud from app.db.session import SessionLocal async def _run_mark_lost_once() -> None: async with SessionLocal() as session: await visit_crud.mark_overdue_as_lost_global(session) async def run_daily_lost_visit_job(stop_event: asyncio.Event) -> None: tz = ZoneInfo("Asia/Shanghai") while not stop_event.is_set(): now = datetime.now(tz) next_midnight = (now + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0) sleep_seconds = max(1, (next_midnight - now).total_seconds()) try: await asyncio.wait_for(stop_event.wait(), timeout=sleep_seconds) break except asyncio.TimeoutError: await _run_mark_lost_once()