Skip to content

fix(pagination): return adjacent page for reverse cursor pagination#3023

Open
abhay-codes07 wants to merge 1 commit into
TracecatHQ:mainfrom
abhay-codes07:fix/reverse-cursor-pagination
Open

fix(pagination): return adjacent page for reverse cursor pagination#3023
abhay-codes07 wants to merge 1 commit into
TracecatHQ:mainfrom
abhay-codes07:fix/reverse-cursor-pagination

Conversation

@abhay-codes07

@abhay-codes07 abhay-codes07 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Checklist

  • Read CONTRIBUTING.md.
  • PR title is short and non-generic (see previously merged PRs for examples).
  • PR only implements a single feature or fixes a single bug.
  • Tests passing (uv run pytest tests)?
  • Lint / pre-commits passing (pre-commit run --all-files)?

Description

Fixes reverse (reverse=true, i.e. "previous page") cursor pagination in three list endpoints. The reference implementations already in the codebase (TableEditorService.list_rows, WorkflowsManagementService.list_workflows) do it in four steps: flip the scan direction, fetch limit + 1, compute cursors from scan order, then reverse the items and swap cursors/flags. Each of the fixed endpoints was missing a different piece:

  • CasesService.search_cases: flipped the cursor comparison but not the ORDER BY, so LIMIT kept the first rows of the whole backward prefix — "previous page" returned page 1 from any page 3 or deeper. It also never swapped has_more/has_previous and its reverse branch overwrote next_cursor while leaving prev_cursor as null. Now uses the canonical scan-flip + reverse + swap.
  • TablesService.list_rows (the search-style method behind search_rows): same missing ORDER BY flip; the post-fetch reversal/swap was already there, so it reversed the wrong window. Now flips the scan direction to match.
  • CaseTableRowsService.list_rows: had two problems. Its reverse branch appended ascending sort keys to a statement already built with .order_by(created_at.desc(), id.desc()) — SQLAlchemy keeps the first sort keys, so the intended flip never took effect and the same wrong window came back. It also computed cursors from the already-reversed items and then swapped them again, so "next" pointed backward and "prev" pointed forward. The reverse branch now replaces the ORDER BY (order_by(None) first), and cursors are computed from scan order before the reversal, like the siblings.

Forward pagination is untouched in all three (the reverse handling is a no-op when reverse is false).

Related Issues

Fixes #3022

Screenshots / Recordings

N/A (API behavior fix)

Steps to QA

uv run pytest tests/unit/test_cases_service.py tests/unit/test_tables_service.py tests/unit/test_case_table_rows_service.py

The new regression tests page three deep and then walk back — the existing reverse tests only went back from page 2, where "previous page" and "page 1" coincide, which is why the bug never surfaced:

  • test_search_cases_reverse_pagination_returns_adjacent_page: back from page 3 returns page 2 (previously page 1), flags are oriented in display direction, and the swapped cursors round-trip forward to page 3 and back to page 1.
  • test_list_rows_reverse_pagination_returns_adjacent_page (tables): same walk over 7 rows with limit=2.
  • test_list_rows_reverse_pagination_cursors_point_forward_and_back (case table rows): after going back a page, next_cursor returns to page 3 and prev_cursor continues to page 1 (previously each pointed the other way).

All pre-existing pagination tests in the three files pass unchanged.


Summary by cubic

Fixes reverse cursor pagination so “previous page” returns the adjacent page with correct cursors and flags across CasesService.search_cases, TablesService.list_rows, and CaseTableRowsService.list_rows. Forward pagination is unchanged.

  • Bug Fixes
    • Implemented the canonical reverse flow: flip scan direction, fetch limit + 1, compute cursors from scan order, then reverse items and swap next/prev and has_more/has_previous. Added regression tests that walk back from page 3 to page 2.
    • CasesService.search_cases and TablesService.list_rows: now flip ORDER BY for reverse scans; case search also fixes swapped/overwritten cursors and flags.
    • CaseTableRowsService.list_rows: replaces (not appends) the base ORDER BY when reversing; computes cursors before reversal and swaps correctly so next points forward and prev points back.

Written for commit 8613676. Summary will update on new commits.

Review in cubic

Copilot AI review requested due to automatic review settings July 11, 2026 17:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@zeropath-ai

zeropath-ai Bot commented Jul 11, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 8613676.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► tracecat/cases/rows/service.py
    Modify list_rows to adjust reverse pagination handling and ordering to reflect display order correctly
► tracecat/cases/service.py
    Adjust search_cases to swap scan direction for reverse pagination and restore display order
Enhancement ► tracecat/tables/service.py
    Modify list_rows to adjust reverse pagination handling and ordering to reflect display order correctly

@topher-lo topher-lo added the fix Bug fix label Jul 13, 2026
@topher-lo

Copy link
Copy Markdown
Contributor

@cubic review

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@cubic review

@topher-lo I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

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

Labels

fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reverse cursor pagination returns the wrong page in cases, tables, and case rows endpoints

3 participants