Description
src/app/actions/maintainer/queue.ts, getMaintainerPrQueue:
- Lines 121-126: fetches a fixed 100-row DB window at offset
Math.floor(page / 4) * 100 (PAGE_SIZE * 4), before any author-level/mentor/AI filtering.
- Lines 131-166: batch-loads profiles; lines 168-190 maps rows; then lines 194-202 filters in app code (
authorLevel >= minContributorLevel, authorLevel, aiFlagged).
- Lines 204-207: sorts via
comparePrRows (src/lib/maintainer/queue.ts:71-78, tiers from prTier lines 59-69) and slices (page % 4) * PAGE_SIZE from the filtered array.
- Line 208:
hasMore = startIdx + PAGE_SIZE < filtered.length || prRows.length === PAGE_SIZE * 4.
getMaintainerIssueQueue (lines 260-320) repeats the same pattern: 100-row DB window → in-app classifyTriage filtering (line 299) → slice.
Expected Behavior
Pagination is stable and complete — every matching row is reachable, pages are non-empty while data remains, and hasMore is accurate.
Actual Behavior
Pages 0-3 all slice the same 100-row DB window, but the DB offset only advances every 4 pages. Under any filter that prunes rows (e.g., default min_contributor_level, or "mentor verified"), the filtered set can be far smaller than 100:
- Pages 1-3 render empty while
hasMore stays true (prRows.length === 100), so the UI offers endless empty pages.
- Matching rows beyond DB offset 100 are unreachable — the user would have to click through 4 empty pages to advance the window, and UIs typically stop paging on empty results.
- Maintainers can miss PRs that should be visible, and
hasMore misleads client-side pagination.
Affected Files
src/app/actions/maintainer/queue.ts (lines 121-126, 131-166, 168-190, 194-208, 260-320) — DB window + in-app filtering + slicing
src/lib/maintainer/queue.ts (lines 59-78) — prTier/comparePrRows sorting helpers
Proposed Fix
Push the filters into SQL (join profiles for level/xp and filter server-side), or replace offset pagination with keyset/cursor pagination over the sorted, filtered result set (e.g., (tier, github_updated_at, id) cursor), or fetch a larger window plus a count(*) query to compute an accurate hasMore. Apply the same fix to both getMaintainerPrQueue and getMaintainerIssueQueue.
Description
src/app/actions/maintainer/queue.ts,getMaintainerPrQueue:Math.floor(page / 4) * 100(PAGE_SIZE * 4), before any author-level/mentor/AI filtering.authorLevel >= minContributorLevel,authorLevel,aiFlagged).comparePrRows(src/lib/maintainer/queue.ts:71-78, tiers fromprTierlines 59-69) and slices(page % 4) * PAGE_SIZEfrom the filtered array.hasMore = startIdx + PAGE_SIZE < filtered.length || prRows.length === PAGE_SIZE * 4.getMaintainerIssueQueue(lines 260-320) repeats the same pattern: 100-row DB window → in-appclassifyTriagefiltering (line 299) → slice.Expected Behavior
Pagination is stable and complete — every matching row is reachable, pages are non-empty while data remains, and
hasMoreis accurate.Actual Behavior
Pages 0-3 all slice the same 100-row DB window, but the DB offset only advances every 4 pages. Under any filter that prunes rows (e.g., default
min_contributor_level, or "mentor verified"), the filtered set can be far smaller than 100:hasMorestaystrue(prRows.length === 100), so the UI offers endless empty pages.hasMoremisleads client-side pagination.Affected Files
src/app/actions/maintainer/queue.ts(lines 121-126, 131-166, 168-190, 194-208, 260-320) — DB window + in-app filtering + slicingsrc/lib/maintainer/queue.ts(lines 59-78) —prTier/comparePrRowssorting helpersProposed Fix
Push the filters into SQL (join
profilesforlevel/xpand filter server-side), or replace offset pagination with keyset/cursor pagination over the sorted, filtered result set (e.g.,(tier, github_updated_at, id)cursor), or fetch a larger window plus acount(*)query to compute an accuratehasMore. Apply the same fix to bothgetMaintainerPrQueueandgetMaintainerIssueQueue.