Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ export class ClickHouseRunsRepository implements IRunsRepository {
previousCursor = reversedRunIds.at(1) ?? null;
nextCursor = reversedRunIds.at(options.page.size) ?? null;
Comment on lines 101 to 102

Choose a reason for hiding this comment

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

🚩 Pre-existing: backward+hasMore branch has inconsistent overflow item handling

In the hasMore backward case (not changed by this PR), the overflow/sentinel item handling appears inconsistent with the forward case.

For forward+hasMore: the query returns [D, C, B, A] (DESC), the code keeps [D, C, B] via runs.slice(0, pageSize), and A is the overflow item (furthest from cursor, oldest). This is correct.

For backward+hasMore: the query returns [A, B, C, D] (ASC), but the code keeps [B, C, D] via runs.slice(1, pageSize+1) at clickhouseRunsRepository.server.ts:117, discarding A (closest to cursor). By analogy with forward, the overflow should be D (furthest from cursor, newest), and the page should display [A, B, C].

This also affects cursor values in the hasMore backward branch at clickhouseRunsRepository.server.ts:101-102:

  • previousCursor = reversedRunIds.at(1) — points to the second-newest item (C), but since "Previous" in the UI triggers direction=backward (see ListPagination.tsx:35), using C as cursor would re-fetch D which is already on the displayed page.
  • nextCursor = reversedRunIds.at(options.page.size) — points to the overflow item A rather than the oldest displayed item B.

This may not cause visible issues in practice if page boundaries overlap by one item (the UI would just show a duplicated boundary item), but it's worth investigating whether users see repeated runs when navigating backward through multiple pages.

(Refers to lines 100-102)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

} else {
nextCursor = reversedRunIds.at(options.page.size - 1) ?? null;
// Use the last item (oldest run) as the forward cursor.
// We can't use a fixed index (pageSize - 1) because the result set
// may have fewer items than pageSize (e.g., when new runs were created
// while the user was browsing, shifting page boundaries).
nextCursor = reversedRunIds.at(reversedRunIds.length - 1) ?? null;
}

break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ export class PostgresRunsRepository implements IRunsRepository {
previousCursor = reversedRuns.at(1)?.id ?? null;
nextCursor = reversedRuns.at(options.page.size)?.id ?? null;
Comment on lines 75 to 76

Choose a reason for hiding this comment

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

🚩 Same pre-existing overflow issue exists in the Postgres repository

The Postgres backward+hasMore branch at postgresRunsRepository.server.ts:74-76 has the same inconsistency as the ClickHouse version — previousCursor and nextCursor are computed from reversedRuns using the same indices, and the runsToReturn slicing at line 89-91 discards the first ASC item rather than the last. This is expected since both repositories mirror each other's pagination logic.

(Refers to lines 74-76)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

} else {
nextCursor = reversedRuns.at(options.page.size - 1)?.id ?? null;
// Use the last item (oldest run) as the forward cursor.
// We can't use a fixed index (pageSize - 1) because the result set
// may have fewer items than pageSize (e.g., when new runs were created
// while the user was browsing, shifting page boundaries).
nextCursor = reversedRuns.at(reversedRuns.length - 1)?.id ?? null;
}
break;
}
Expand Down