Review
Live freight checkpoint feed uses offset as cursor
Yard ops asked for infinite scroll on the live checkpoint feed so dispatchers can page through car arrivals without full reloads. This PR renames page/limit to cursor/limit and returns next_cursor so the React board can keep scrolling as railcars ping RFID gates.
FastAPITier 4paginationkeysetconcurrencyfastapi
Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.
apps/yard_api/routers/checkpoints.py+13-10
| 48 | 48 | @router.get("/yards/{yard_id}/checkpoints") | |
| 49 | - | async def list_checkpoints( | |
| 50 | - | yard_id: UUID, | |
| 51 | - | page: int = Query(1, ge=1), | |
| 52 | - | limit: int = Query(50, ge=1, le=200), | |
| 53 | - | db: AsyncSession = Depends(get_db), | |
| 54 | - | ) -> CheckpointPage: | |
| 49 | + | async def list_checkpoints( | |
| 50 | + | yard_id: UUID, | |
| 51 | + | cursor: str | None = Query(None, description="Opaque pagination cursor"), | |
| 52 | + | limit: int = Query(50, ge=1, le=200), | |
| 53 | + | db: AsyncSession = Depends(get_db), | |
| 54 | + | ) -> CheckpointPage: | |
| 55 | 55 | await require_yard_access(db, yard_id) | |
| 56 | - | offset = (page - 1) * limit | |
| 56 | + | # cursor is the page index clients already fetched; default to first page | |
| 57 | + | page = int(cursor) if cursor is not None else 1 | |
| 58 | + | offset = (page - 1) * limit | |
| 57 | 59 | stmt = ( | |
| 58 | 60 | select(CheckpointEvent) | |
| 59 | 61 | .where(CheckpointEvent.yard_id == yard_id) | |
| 60 | 62 | .order_by(CheckpointEvent.recorded_at.desc(), CheckpointEvent.id.desc()) | |
| 61 | - | .offset(offset) | |
| 62 | - | .limit(limit) | |
| 63 | + | .offset(offset) | |
| 64 | + | .limit(limit) | |
| 63 | 65 | ) | |
| 64 | 66 | rows = (await db.scalars(stmt)).all() | |
| 65 | - | return CheckpointPage(items=rows, page=page, limit=limit) | |
| 67 | + | next_cursor = str(page + 1) if len(rows) == limit else None | |
| 68 | + | return CheckpointPage(items=rows, next_cursor=next_cursor, limit=limit) |