Skip to content

cursor-based pagination with stable ordering for the route list #553

Description

@mikewheeleer

Summary

The route list uses offset pagination, which skips/duplicates rows when data changes mid-scan and degrades on large offsets. Replace it with opaque-cursor pagination with a stable total order.

Why this matters

Offset pagination is incorrect under concurrent writes and slow at scale. Cursors give stable, efficient, resumable iteration.

Requirements

  • Add opaque-cursor pagination to the route list with a bounded page size.
  • Order by a stable, unique key (e.g. created-at + id tiebreak).
  • Return a nextCursor (null at end); reject malformed/expired cursors with 400.
  • Keep the response envelope stable and documented.

Technical guidance

  • Encode the cursor opaquely (base64 of the sort key) — never leak internal offsets.
  • Use a compound key so ties are deterministic.

Edge cases — each must have a test

  • first page then next -> no gaps or duplicates
  • rows inserted mid-scan -> no skipped/duplicated existing rows
  • end of list -> nextCursor is null
  • invalid cursor -> 400
  • page size clamps to the max

Acceptance criteria

  • All requirements and every edge case above implemented and covered by tests
  • New unit and integration tests; existing tests still pass and no regressions
  • Structured, typed errors (no leaked internals; stable codes)
  • npm run lint, npm test, and npm run build all pass locally
  • Code follows the repo's existing conventions; no duplication or dead code
  • Short docs/comments explaining the design and any non-obvious decisions
  • PR description explains the approach and includes Closes #<issue>

Out of scope

  • Bidirectional (previous) paging
  • Total-count on every page

Rewards

Part of the GrantFox OSS / Official Campaign (FWC26) — this task may be rewarded. PR quality is assessed by AI: depth, correctness under edge cases, meaningful tests, and clean design are what earn the reward. Shallow changes (typos, formatting, trivial docs) do not qualify.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions