Skip to content

Conversation

@samwillis
Copy link
Collaborator

@samwillis samwillis commented Dec 3, 2025

Summary

This PR enhances LoadSubsetOptions with separate cursor expressions and offset support, allowing sync layers to choose between cursor-based or offset-based pagination strategies.

API Changes:

  • Add CursorExpressions type with whereFrom, whereCurrent, and optional lastKey properties
  • LoadSubsetOptions.where no longer includes cursor expressions - these are now passed separately via cursor
  • Add offset to LoadSubsetOptions for offset-based pagination support
  • Electric sync layer now makes two parallel requestSnapshot calls when cursor is present:
    • One for whereCurrent (all ties at boundary, no limit)
    • One for whereFrom (rows after cursor, with limit)
  • Query collection serialization now includes offset for query key generation
  • Add truncate event to collections, emitted when synced data is truncated (e.g., after must-refetch)

Bug Fixes:

  • Fixed setWindow pagination: cursor expressions are now correctly built when paging through multi-column orderBy results
  • Fixed offset tracking: loadNextItems now passes the correct window offset to prevent incorrect deduplication
  • CollectionSubscriber now listens for truncate events to reset cursor tracking state, preventing stale cursor data after must-refetch

Benefits

  • Sync layers can choose between cursor-based or offset-based pagination strategies
  • Electric can efficiently handle tie-breaking with two targeted requests
  • Better separation of concerns between filtering (where) and pagination (cursor/offset)
  • setWindow correctly triggers backend loading for subsequent pages in multi-column orderBy queries
  • Cursor state is properly reset after truncation

Stacked PR

This PR is stacked on #926 (samwillis/order-by-improvments)

Test plan

  • All unit tests pass for @tanstack/db, @tanstack/electric-db-collection, @tanstack/query-db-collection
  • E2E tests pass for electric-db-collection and query-db-collection
  • Updated test expectations for reduced requestSnapshot call counts (cursor-based pagination is more efficient)
  • Multi-column orderBy pagination tests pass with setWindow

@changeset-bot
Copy link

changeset-bot bot commented Dec 3, 2025

🦋 Changeset detected

Latest commit: cc8fccb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@tanstack/db Patch
@tanstack/electric-db-collection Patch
@tanstack/query-db-collection Patch
@tanstack/angular-db Patch
@tanstack/db-collection-e2e Patch
@tanstack/offline-transactions Patch
@tanstack/powersync-db-collection Patch
@tanstack/react-db Patch
@tanstack/rxdb-db-collection Patch
@tanstack/solid-db Patch
@tanstack/svelte-db Patch
@tanstack/trailbase-db-collection Patch
@tanstack/vue-db Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 3, 2025

More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@960

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@960

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@960

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@960

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@960

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@960

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@960

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@960

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@960

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@960

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@960

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@960

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@960

commit: cc8fccb

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

Size Change: +231 B (+0.26%)

Total Size: 88.4 kB

Filename Size Change
./packages/db/dist/esm/collection/index.js 3.24 kB +1 B (+0.03%)
./packages/db/dist/esm/collection/state.js 3.46 kB +39 B (+1.14%)
./packages/db/dist/esm/collection/subscription.js 2.78 kB +67 B (+2.47%)
./packages/db/dist/esm/index.js 2.67 kB +11 B (+0.41%)
./packages/db/dist/esm/query/live/collection-subscriber.js 1.79 kB +55 B (+3.17%)
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB +58 B (+1.99%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 977 B
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/lifecycle.js 1.67 kB
./packages/db/dist/esm/collection/mutations.js 2.31 kB
./packages/db/dist/esm/collection/sync.js 2.37 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.19 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 1.93 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 513 B
./packages/db/dist/esm/local-only.js 837 B
./packages/db/dist/esm/local-storage.js 2.1 kB
./packages/db/dist/esm/optimistic-action.js 359 B
./packages/db/dist/esm/paced-mutations.js 496 B
./packages/db/dist/esm/proxy.js 3.75 kB
./packages/db/dist/esm/query/builder/functions.js 733 B
./packages/db/dist/esm/query/builder/index.js 3.96 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 917 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.35 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 1.8 kB
./packages/db/dist/esm/query/compiler/index.js 1.96 kB
./packages/db/dist/esm/query/compiler/joins.js 2 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.46 kB
./packages/db/dist/esm/query/compiler/select.js 1.07 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.33 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/internal.js 130 B
./packages/db/dist/esm/query/optimizer.js 2.56 kB
./packages/db/dist/esm/query/subset-dedupe.js 921 B
./packages/db/dist/esm/scheduler.js 1.3 kB
./packages/db/dist/esm/SortedMap.js 1.3 kB
./packages/db/dist/esm/strategies/debounceStrategy.js 247 B
./packages/db/dist/esm/strategies/queueStrategy.js 428 B
./packages/db/dist/esm/strategies/throttleStrategy.js 246 B
./packages/db/dist/esm/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 881 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 852 B
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

compressed-size-action::db-package-size

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

Size Change: 0 B

Total Size: 3.35 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.17 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.12 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 431 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

compressed-size-action::react-db-package-size

@samwillis samwillis mentioned this pull request Dec 3, 2025
@samwillis samwillis force-pushed the samwillis/cursor-pagination branch 11 times, most recently from 6d0a91a to f1a6d36 Compare December 4, 2025 12:23
@kevin-dp kevin-dp self-requested a review December 4, 2025 14:51
@samwillis samwillis force-pushed the samwillis/order-by-improvments branch 2 times, most recently from 7f03f25 to e5dc9f7 Compare December 5, 2025 17:13
Base automatically changed from samwillis/order-by-improvments to main December 5, 2025 17:18
…e in loadSubset

- Add CursorExpressions type with whereFrom, whereCurrent, and lastKey
- LoadSubsetOptions.where no longer includes cursor - passed separately via cursor property
- Add offset to LoadSubsetOptions for offset-based pagination support
- Electric sync layer makes two parallel requestSnapshot calls when cursor present
- Query collection serialization includes offset for query key generation

This allows sync layers to choose between cursor-based or offset-based pagination,
and Electric can efficiently handle tie-breaking with targeted requests.

test(react-db): update useLiveInfiniteQuery test mock to handle cursor expressions

The test mock's loadSubset handler now handles the new cursor property
in LoadSubsetOptions by combining whereCurrent (ties) and whereFrom (next page)
data, deduplicating by id, and re-sorting.

fix(electric): make cursor requestSnapshot calls sequential

Changed parallel requestSnapshot calls to sequential to avoid potential
issues with concurrent snapshot requests that may cause timeouts in CI.

fix(electric): combine cursor expressions into single requestSnapshot

Instead of making two separate requestSnapshot calls (one for whereFrom,
one for whereCurrent), combine them using OR into a single request.
This avoids potential issues with multiple sequential snapshot requests
that were causing timeouts in CI.

The combined expression (whereFrom OR whereCurrent) matches the original
behavior where cursor was combined with the where clause.

wip

working?

update changeset

fix query test
@samwillis samwillis force-pushed the samwillis/cursor-pagination branch from ff54e90 to 091f214 Compare December 5, 2025 17:29
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.

3 participants