Skip to content

Use built-in pagination instead of paginator - #72

Closed
ianmacartney wants to merge 1 commit into
mainfrom
ian/built-in-paginate
Closed

ianmacartney wants to merge 1 commit into
mainfrom
ian/built-in-paginate

Conversation

@ianmacartney

Copy link
Copy Markdown
Member

Migrations now page through tables with built-in ctx.db.query(table).paginate() by default, in place of the paginator from convex-helpers/server/pagination.

This depends on the upcoming Convex release, which lets components call .paginate() once per transaction. It temporarily installs convex-test from https://pkg.pr.new/convex-test@163 (devDependency), which enforces that limit, until a real release.

Changes

  • src/client/index.ts: each migration batch uses ctx.db.query(table) (plus customRange) and .paginate(). The paginator is kept only as a fallback for legacy cursors: if the stored cursor came from the paginator (versions 0.3.5-0.3.7), that batch and later ones resume with the paginator, so in-progress migrations keep going. Adds an exported isPaginatorCursor(cursor). It is true when the cursor is a JSON array ending in a numeric _creationTime and a string _id, so it does not match convex-test's built-in cursors, which are JSON arrays of strings. isNewFormatCursor is still exported, marked deprecated, and behaves as before.
  • schema option: no longer required for customRange. It still gives type safety. At runtime it is only needed to resume a legacy paginator cursor on a migration that has a customRange. Without it, that case throws an error saying to pass the schema or restart from a null cursor.
  • README, schema JSDoc, and the example/convex/localComponent/example.ts comment are updated to match.
  • Tests: isPaginatorCursor unit tests, plus a test that resumes a migration from a paginator cursor. The runToCompletion tests now run in t.action rather than t.run, since runToCompletion needs an action context and loops over runMutation. Under t.run all batches share one transaction, which the new convex-test rejects.
  • convex-helpers stays as a peer dependency because the legacy fallback still uses it.

One paginate per transaction

Each migration batch calls .paginate() once. When migrations.runOne, runSerially, or a migration function is called from a mutation, the first batch runs inside the caller's transaction. So a mutation that already paginated, or that starts two migrations, will now fail on that call. migrateOne callbacks that call .paginate() themselves will also fail. Later batches run in their own scheduled transactions. runToCompletion runs each batch in its own transaction when called from an action.

Migrations now paginate with ctx.db.query(table).paginate() by default,
which components can call once per transaction. The convex-helpers
paginator is only used to resume in-progress migrations whose stored
cursor came from the paginator (versions 0.3.5-0.3.7). The schema option
is no longer required for customRange, except to resume such a legacy
cursor with a custom range.

Adds isPaginatorCursor (isNewFormatCursor is kept, deprecated), installs
convex-test from pkg.pr.new for the one-paginate-per-transaction check,
and runs runToCompletion in tests from an action context.
@pkg-pr-new

pkg-pr-new Bot commented Oct 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@convex-dev/migrations@72

commit: 86b6040

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