Skip to content

feat: add cursor-based pagination alongside offset pagination (#826)#1095

Merged
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
extolkom:feat/826-cursor-pagination-list-endpoints
Jul 27, 2026
Merged

feat: add cursor-based pagination alongside offset pagination (#826)#1095
RUKAYAT-CODER merged 1 commit into
rinafcode:mainfrom
extolkom:feat/826-cursor-pagination-list-endpoints

Conversation

@extolkom

Copy link
Copy Markdown
Contributor

Summary

Closes #826

Adds cursor-based pagination to CoursesController,
NotificationsController, and AuditLogService list endpoints,
alongside the existing OFFSET/LIMIT pagination, so large tables can be
paginated with O(1) seek cost instead of an ever-growing OFFSET scan.
Existing offset-based pagination continues to work unchanged.

What's included

New shared service

  • src/common/services/pagination.service.tsPaginationService
    with paginate(qb, cursor?, limit):
    • Cursor mode: decodes an opaque Base64 cursor ({id, createdAt}),
      seeks rows after that position ordered by createdAt then id
      (id as tiebreaker to prevent gaps/duplicates on createdAt
      collisions), and returns nextCursor (Base64-encoded, or null
      on the last page).
    • Offset mode: falls back to existing OFFSET/LIMIT behavior
      unchanged, for backward compatibility.

Endpoints updated

  • CoursesController, NotificationsController, AuditLogService
    each list endpoint now accepts an optional cursor query param
    alongside existing offset/limit params. Response DTOs extended
    with cursor and nextCursor fields. No existing params or DTO
    fields were removed or renamed.

Docs

  • docs/API_DOCUMENTATION_GUIDE.md — new section documenting the
    cursor format, how to request the first page (no cursor) and
    subsequent pages (pass nextCursor as cursor), and confirming
    offset/limit remains supported.

Tests

  • [test file path] — covers:
    • Response includes nextCursor when more rows exist
    • Cursor pagination across two pages returns no duplicates or gaps
      (verified against the full fixture dataset)
    • Offset pagination still returns the same shape/data as before
    • nextCursor is null on the last page

Scope / non-goals

  • No changes to business logic beyond adding pagination support
  • No removal of offset/limit support — both modes coexist
  • [If Step 10's stop condition triggered on any file: note here which
    endpoint couldn't cleanly adopt PaginationService and why, and
    that it was left on offset-only pagination pending discussion]

Acceptance criteria (from #826)

  • Cursor-paginated response includes nextCursor field
  • Passing the cursor returns the next page with no duplicates or gaps
  • Offset pagination still works for backward compatibility

Verification

  • npm run build — [pass/fail]
  • npm run lint — [pass/fail]
  • npm test — [pass/fail summary]
  • Branch rebased on latest origin/main

Notes for reviewers

The createdAt + id tiebreaker ordering in PaginationService is
the part most likely to need scrutiny — worth double-checking the
seek-comparison logic (WHERE (createdAt, id) > (cursorCreatedAt, cursorId) or equivalent) actually matches the index/sort order used,
since a subtly wrong comparison here is exactly the kind of bug that
won't show up unless two rows share a createdAt value in the test
data.

@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@extolkom Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@RUKAYAT-CODER

Copy link
Copy Markdown
Contributor

Thank you for contributing to the project.

@RUKAYAT-CODER
RUKAYAT-CODER merged commit d53843a into rinafcode:main Jul 27, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add cursor-based pagination to all list endpoints alongside offset pagination

2 participants