"""Cron entrypoint. Runs as a FastAPI app (for /health/cron) with APScheduler spawning the time-triggered jobs. P1 jobs are added in week 2 task #8 (polling) and week 3 tasks #12 (SLO measurement) and #13 (contract checker). """ from collections.abc import AsyncIterator from contextlib import asynccontextmanager import structlog from apscheduler.schedulers.asyncio import AsyncIOScheduler from fastapi import FastAPI from app.config import get_settings from app.db import close_pool, get_pool from app.health import router as health_router from app.logging_setup import configure_logging log = structlog.get_logger("cron") @asynccontextmanager async def lifespan(_: FastAPI) -> AsyncIterator[None]: configure_logging() settings = get_settings() await get_pool() log.info("cron.starting", git_sha=settings.app_git_sha, mode=settings.app_mode) scheduler = AsyncIOScheduler(timezone="UTC") scheduler.start() log.info("cron.scheduler_started") try: yield finally: scheduler.shutdown(wait=False) await close_pool() app = FastAPI( title="fleet-platform [cron]", version=get_settings().app_git_sha, lifespan=lifespan, ) app.include_router(health_router)