feat: paginate list endpoints with X-Total-Count (#99) #170
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/99-pagination"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
No backend list endpoint paginated — unbounded response sizes/query times as campaigns accumulate data. Adds
limit/offset+ anX-Total-Countheader to the list endpoints, uniformly.Design
app/pagination.pydependency so the convention is identical everywhere:limitdefault 200 (ge=1→ 422 on 0/negative), clamped in code to max 500 (notle=, which would 422 — the spec wants clamp);offsetdefault 0 (ge=0).X-Total-Countheader (chosen over an envelope — fully backward compatible; the body stays a plain JSON array). Each endpoint runs acount()for the total and a page query with an explicitORDER BY … , idunique tiebreaker (no shuffle/overlap).docs/API.md.Endpoints paginated (9)
sessions, members, npcs, lore, lore/proposals, planning/arcs, planning/threads, session votes, and
/api/bot/sessions/upcoming(default 200 keeps the bot'sget_upcoming_sessionsworking unchanged).Deliberately skipped (with reasons):
milestones— it appends synthesized "NPC reappeared" entries after the DB query, so a DBcount()/limitwould give a wrongX-Total-Countand overlapping pages (paginating it would be incorrect, not just harder);analytics— aggregate object, not a list; plus bounded GM-only/search/graph lists left for focus.Frontend
"Load more" (accumulate-append) on the two lists that can realistically exceed 200: session list (
CampaignDetail.jsx) and wiki entry list (CampaignStoryline.jsx); new API helpers readX-Total-Count.Behaviour change
Any of the 9 endpoints that previously returned >200 rows by default is now capped at 200 unless the caller raises
limit. Under 200 rows, no-param behaviour is identical.Verification
Backend 388 passed (+6 pagination tests: two-page no-overlap + header on sessions & bot/upcoming, clamp-not-reject, default-under-cap, a 422 matrix, dependency clamp unit). Frontend 67 passed (one unrelated pre-existing
react-markdownstale-dep failure in an untouched file). ruff 0.4.4 clean.Closes #99
🤖 Generated with Claude Code