Skip to content

Fix duplicate partners in paginated list and API#4095

Draft
pepeladeira wants to merge 5 commits into
mainfrom
fix-partners-pagination
Draft

Fix duplicate partners in paginated list and API#4095
pepeladeira wants to merge 5 commits into
mainfrom
fix-partners-pagination

Conversation

@pepeladeira

@pepeladeira pepeladeira commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Bug Fixes
    • Improved /partners offset pagination to return results in a deterministic, stable order across pages by adding an id tie-breaker when multiple records share the same sort value.
  • Tests
    • Added concurrent end-to-end integration tests for /partners pagination that request multiple offset pages, verify item counts, ensure no overlap between pages, and confirm the combined ordering matches the expected baseline sequence.

@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dub Ready Ready Preview Jul 1, 2026 8:29pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4494a832-6bee-4fe3-81b4-bd257a633482

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Partner pagination now uses a secondary id sort for stable ordering, removes an offset-pagination comment, and adds an integration test that verifies three paged responses do not overlap and match a baseline id sequence.

Changes

Partners Pagination Fix

Layer / File(s) Summary
Deterministic partner ordering
apps/web/lib/api/pagination.ts, apps/web/lib/api/partners/get-partners.ts
getPartners now sorts by the requested field and then by id, and the offset-pagination comment is removed.
Offset pagination integration test
apps/web/tests/partners/pagination.test.ts
New Vitest coverage fetches a baseline list, then pages 1–3, and checks counts, uniqueness, overlap, and baseline-prefix ordering.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: steven-tey

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing duplicate partners in paginated API results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-partners-pagination

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pepeladeira
pepeladeira marked this pull request as ready for review June 29, 2026 20:02

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/tests/partners/pagination.test.ts`:
- Around line 18-30: The pagination test setup in beforeAll for
pagination.test.ts does not verify that the fixture is large enough to cover
three full pages, so it can pass without exercising the boundary case. Update
the shared setup and the page assertions around the /partners requests to
confirm the baseline contains at least 15 enrolled partners, then explicitly
assert that pages 1, 2, and 3 each return 5 rows using the existing h.init(),
http.get, baseline, and baselineIds flow so the duplicate issue is actually
covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2df3878d-6722-4523-abee-79c990942964

📥 Commits

Reviewing files that changed from the base of the PR and between 4b11398 and 15e0116.

📒 Files selected for processing (3)
  • apps/web/lib/api/pagination.ts
  • apps/web/lib/api/partners/get-partners.ts
  • apps/web/tests/partners/pagination.test.ts

Comment thread apps/web/tests/partners/pagination.test.ts Outdated
@pepeladeira

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review, any breaking changes?

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Changed files vs origin/main =="
git diff --name-only origin/main...HEAD

echo
echo "== Diffstat =="
git diff --stat origin/main...HEAD

echo
echo "== Diff: apps/web/lib/api/pagination.ts =="
git diff --unified=60 origin/main...HEAD -- apps/web/lib/api/pagination.ts

echo
echo "== Diff: apps/web/lib/api/partners/get-partners.ts =="
git diff --unified=80 origin/main...HEAD -- apps/web/lib/api/partners/get-partners.ts

echo
echo "== Diff: apps/web/tests/partners/pagination.test.ts =="
git diff --unified=80 origin/main...HEAD -- apps/web/tests/partners/pagination.test.ts

echo
echo "== AST outline: apps/web/lib/api/pagination.ts =="
ast-grep outline apps/web/lib/api/pagination.ts --view expanded || true

echo
echo "== AST outline: apps/web/lib/api/partners/get-partners.ts =="
ast-grep outline apps/web/lib/api/partners/get-partners.ts --view expanded || true

echo
echo "== Usages of buildPaginationQuery =="
rg -n -C2 '\bbuildPaginationQuery\s*\(' apps/web

echo
echo "== Relevant slice: apps/web/lib/api/pagination.ts =="
sed -n '1,240p' apps/web/lib/api/pagination.ts

echo
echo "== Relevant slice: apps/web/lib/api/partners/get-partners.ts =="
sed -n '1,260p' apps/web/lib/api/partners/get-partners.ts

Length of output: 16708


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Diff: apps/web/app/api/ai/support-chat/route.ts =="
git diff --unified=80 origin/main...HEAD -- apps/web/app/api/ai/support-chat/route.ts

echo
echo "== Diff: apps/web/lib/ai/build-system-prompt.ts =="
git diff --unified=120 origin/main...HEAD -- apps/web/lib/ai/build-system-prompt.ts

echo
echo "== Diff: apps/web/lib/ai/get-plan-comparison.ts =="
git diff --unified=120 origin/main...HEAD -- apps/web/lib/ai/get-plan-comparison.ts

echo
echo "== Diff: apps/web/lib/ai/plan-context.ts =="
git diff --unified=160 origin/main...HEAD -- apps/web/lib/ai/plan-context.ts

echo
echo "== Relevant slices of shared-pagination consumers =="
for f in \
  apps/web/lib/customers/api/get-customers.ts \
  apps/web/lib/api/links/get-links-for-workspace.ts \
  apps/web/lib/api/commissions/get-commissions.ts
do
  echo
  echo "-- $f --"
  sed -n '1,220p' "$f"
done

echo
echo "== Search for assumptions about exact tied-order pagination =="
rg -n -C2 'pageSize|startingAfter|endingBefore|sortBy|sortOrder|baselineIds|expectNoOverlap' apps/web/tests apps/web/lib

Length of output: 149453


@pepeladeira I did a full pass on the diff.

Short answer: no obvious breaking changes to the public API contract.

What I found:

  • apps/web/lib/api/partners/get-partners.ts now uses the shared pagination helper, which fixes the duplicate-across-pages issue and keeps the same response shape.
  • apps/web/tests/partners/pagination.test.ts adds a solid regression test for the pagination bug.
  • The AI support-chat changes add an internal plan-comparison tool/prompt path only; I don’t see a public contract change there.

One compatibility note:

  • apps/web/lib/api/pagination.ts now applies a secondary id sort for offset pagination: [{ [sortBy]: sortOrder }, { id: sortOrder }].
  • Because buildPaginationQuery() is shared, this slightly changes the ordering of records that are tied on the primary sort field for:
    • /partners
    • /customers
    • /links
    • /commissions

So I’d classify it as:

  • Not a schema-breaking change
  • Not a parameter-breaking change
  • Low-risk behavioral change in tie ordering

That tie-break change is probably the right fix here, but if any client depends on the exact previous order of equal-valued rows, they could observe different pagination results.

✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
apps/web/lib/api/partners/get-partners.ts (1)

57-59: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Reuse the shared pagination helper here. get-partners.ts now duplicates the offset-pagination take/skip/orderBy logic and adds its own id tiebreak, while buildPaginationQuery still only returns a single-field orderBy for offset pagination. If partners needs that secondary sort, extend the shared helper to support it and use it here to avoid drift from the other list APIs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/api/partners/get-partners.ts` around lines 57 - 59,
`get-partners.ts` is duplicating the offset pagination query shape instead of
using the shared `buildPaginationQuery` helper. Update `buildPaginationQuery` to
support an optional secondary sort/tiebreak field for offset pagination, then
switch `get-partners` to call that helper so the `take`/`skip`/`orderBy` logic
stays consistent with the other list APIs. Use the shared pagination symbols
(`buildPaginationQuery`, the partners list query builder) to keep the sorting
behavior centralized and avoid drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/web/lib/api/partners/get-partners.ts`:
- Around line 57-59: `get-partners.ts` is duplicating the offset pagination
query shape instead of using the shared `buildPaginationQuery` helper. Update
`buildPaginationQuery` to support an optional secondary sort/tiebreak field for
offset pagination, then switch `get-partners` to call that helper so the
`take`/`skip`/`orderBy` logic stays consistent with the other list APIs. Use the
shared pagination symbols (`buildPaginationQuery`, the partners list query
builder) to keep the sorting behavior centralized and avoid drift.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4c0bf31-6f33-4b7c-b6c7-bb1dc95524bb

📥 Commits

Reviewing files that changed from the base of the PR and between 2b593b5 and 0eb859f.

📒 Files selected for processing (2)
  • apps/web/lib/api/pagination.ts
  • apps/web/lib/api/partners/get-partners.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/web/lib/api/pagination.ts

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.

1 participant