from fastapi import APIRouter, Depends, Query from sqlalchemy import and_, or_, select from sqlalchemy.ext.asyncio import AsyncSession from ..cursors import decode, encode from ..db import get_session from ..models import Check from ..schemas import ID_PATTERN, ChecksPage, CheckState from ..timeutil import to_utc router = APIRouter() @router.get("/checks", response_model=ChecksPage) async def list_checks( agent_id: str | None = Query(default=None, max_length=128, pattern=ID_PATTERN), cursor: str | None = Query(default=None, max_length=512), limit: int = Query(default=100, ge=1, le=500), session: AsyncSession = Depends(get_session), ) -> ChecksPage: stmt = select(Check).order_by(Check.agent_id, Check.check_id) if agent_id is not None: stmt = stmt.where(Check.agent_id == agent_id) if cursor is not None: last_agent, last_check = decode(cursor, 2) stmt = stmt.where( or_( Check.agent_id > last_agent, and_(Check.agent_id == last_agent, Check.check_id > last_check), ) ) rows = (await session.execute(stmt.limit(limit + 1))).scalars().all() next_cursor = None if len(rows) > limit: rows = rows[:limit] next_cursor = encode(rows[-1].agent_id, rows[-1].check_id) items = [ CheckState( agent_id=r.agent_id, check_id=r.check_id, status=r.status, last_observed_at=to_utc(r.last_observed_at), exit_code=r.exit_code, incident_key=r.incident_key, summary=r.summary, ) for r in rows ] return ChecksPage(items=items, next_cursor=next_cursor)