Skip to content

feat(db): shared live-query window controller (RFC #1623 phase 5)#1675

Open
kevin-dp wants to merge 5 commits into
phase4/ordered-layout-contractfrom
phase5/window-controller
Open

feat(db): shared live-query window controller (RFC #1623 phase 5)#1675
kevin-dp wants to merge 5 commits into
phase4/ordered-layout-contractfrom
phase5/window-controller

Conversation

@kevin-dp

Copy link
Copy Markdown
Contributor

Draft — Phase 5 of the live-query platform RFC (#1623): extract the infinite/windowed-query state machine into a shared controller. Stacked on #1669 (Phase 4) → #1642 (observer); base is phase4/ordered-layout-contract so the diff is Phase 5 only.

What

Adds createLiveQueryWindowController to @tanstack/db — the framework-agnostic forward-pagination state machine, composing the shared live-query observer. It owns:

  • loadedPageCount and the peek-ahead window (limit = loadedPages * pageSize + 1) applied via collection.utils.setWindow
  • page slicing into pages/pageParams, hasNextPage (peek row present), isFetchingNextPage
  • a reactivity-free getSnapshot / subscribe / fetchNextPage / reset / dispose surface, mirroring the observer

react-db's useLiveInfiniteQuery is reimplemented as a thin binding over it (input resolution + useSyncExternalStore) with no public API change — its full existing suite (31 tests) stays green as the faithfulness anchor.

Faithful extraction (v1)

Behavior is preserved exactly: forward-append only (offset always 0), peek-ahead hasNextPage, getNextPageParam still accepted-but-unused. No new semantics. The point of this PR is the shared controller, not a redesign.

Why draft / open questions

Per the RFC, Phase 5's risk is coordination, not code. Flagging for discussion before finalizing:

Tests

  • packages/db/tests/live-query-window-controller.test.ts — core: peek-ahead first page, fetchNextPage through exhaustion, partial last page, no-op when no next page, reset, stable snapshot identity, disabled controller.
  • react-db useLiveInfiniteQuery suite (31) unchanged and green — proves the extraction is behavior-preserving.

Full @tanstack/db suite (2478) and react-db suite (122) green.

🤖 Generated with Claude Code

Extracts the forward-pagination state machine out of react-db's
useLiveInfiniteQuery into a framework-agnostic createLiveQueryWindowController
in @tanstack/db, composing the shared live-query observer.

The controller owns loadedPageCount, the peek-ahead window (via
collection.utils.setWindow), page slicing, and hasNextPage/isFetchingNextPage,
and exposes a reactivity-free getSnapshot/subscribe/fetchNextPage/reset/dispose
surface mirroring the observer. react-db's useLiveInfiniteQuery is now a thin
binding over it with no public API change; its existing suite stays green.
Vue/Svelte/Solid/Angular can build infinite queries on the same controller
instead of re-porting React's logic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

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: 05a7436a-c64a-4c40-996e-aef676fba415

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch phase5/window-controller

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.

autofix-ci Bot and others added 2 commits July 15, 2026 11:50
UseLiveInfiniteQueryReturn references ReturnType<typeof useLiveQuery>, but the
import was dropped in the controller rewrite. vitest's typecheck missed it;
the package build (strict tsc) caught it (TS2304). Re-add as a type-only import.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@pkg-pr-new

pkg-pr-new Bot commented Jul 15, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-db

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

@tanstack/browser-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/browser-db-sqlite-persistence@1675

@tanstack/capacitor-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/capacitor-db-sqlite-persistence@1675

@tanstack/cloudflare-durable-objects-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/cloudflare-durable-objects-db-sqlite-persistence@1675

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/db-sqlite-persistence-core

npm i https://pkg.pr.new/@tanstack/db-sqlite-persistence-core@1675

@tanstack/electric-db-collection

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

@tanstack/electron-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/electron-db-sqlite-persistence@1675

@tanstack/expo-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/expo-db-sqlite-persistence@1675

@tanstack/node-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/node-db-sqlite-persistence@1675

@tanstack/offline-transactions

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

@tanstack/powersync-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/react-native-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/react-native-db-sqlite-persistence@1675

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/tauri-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/tauri-db-sqlite-persistence@1675

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: 5d50a0c

@github-actions

Copy link
Copy Markdown
Contributor

Size Change: +1.25 kB (+0.99%)

Total Size: 128 kB

📦 View Changed
Filename Size Change
packages/db/dist/esm/index.js 3.22 kB +34 B (+1.07%)
packages/db/dist/esm/live-query-window-controller.js 1.22 kB +1.22 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size
packages/db/dist/esm/collection/change-events.js 1.43 kB
packages/db/dist/esm/collection/changes.js 1.56 kB
packages/db/dist/esm/collection/cleanup-queue.js 810 B
packages/db/dist/esm/collection/events.js 434 B
packages/db/dist/esm/collection/index.js 3.62 kB
packages/db/dist/esm/collection/indexes.js 1.99 kB
packages/db/dist/esm/collection/lifecycle.js 1.69 kB
packages/db/dist/esm/collection/mutations.js 2.47 kB
packages/db/dist/esm/collection/state.js 5.4 kB
packages/db/dist/esm/collection/subscription.js 3.74 kB
packages/db/dist/esm/collection/sync.js 2.88 kB
packages/db/dist/esm/collection/transaction-metadata.js 144 B
packages/db/dist/esm/deferred.js 207 B
packages/db/dist/esm/errors.js 5.1 kB
packages/db/dist/esm/event-emitter.js 748 B
packages/db/dist/esm/indexes/auto-index.js 829 B
packages/db/dist/esm/indexes/base-index.js 767 B
packages/db/dist/esm/indexes/basic-index.js 2.06 kB
packages/db/dist/esm/indexes/btree-index.js 2.19 kB
packages/db/dist/esm/indexes/index-registry.js 820 B
packages/db/dist/esm/indexes/reverse-index.js 557 B
packages/db/dist/esm/live-query-adapter.js 318 B
packages/db/dist/esm/live-query-observer.js 1.16 kB
packages/db/dist/esm/local-only.js 916 B
packages/db/dist/esm/local-storage.js 2.12 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 1.47 kB
packages/db/dist/esm/query/builder/index.js 5.84 kB
packages/db/dist/esm/query/builder/ref-proxy.js 1.24 kB
packages/db/dist/esm/query/compiler/evaluators.js 1.89 kB
packages/db/dist/esm/query/compiler/expressions.js 430 B
packages/db/dist/esm/query/compiler/group-by.js 3.56 kB
packages/db/dist/esm/query/compiler/index.js 6.67 kB
packages/db/dist/esm/query/compiler/joins.js 2.5 kB
packages/db/dist/esm/query/compiler/lazy-targets.js 923 B
packages/db/dist/esm/query/compiler/order-by.js 1.74 kB
packages/db/dist/esm/query/compiler/select.js 1.53 kB
packages/db/dist/esm/query/effect.js 4.77 kB
packages/db/dist/esm/query/expression-helpers.js 1.43 kB
packages/db/dist/esm/query/ir.js 1.25 kB
packages/db/dist/esm/query/live-query-collection.js 360 B
packages/db/dist/esm/query/live/collection-config-builder.js 9.27 kB
packages/db/dist/esm/query/live/collection-registry.js 264 B
packages/db/dist/esm/query/live/collection-subscriber.js 1.93 kB
packages/db/dist/esm/query/live/internal.js 145 B
packages/db/dist/esm/query/live/utils.js 1.81 kB
packages/db/dist/esm/query/optimizer.js 2.92 kB
packages/db/dist/esm/query/predicate-utils.js 2.97 kB
packages/db/dist/esm/query/query-once.js 359 B
packages/db/dist/esm/query/subset-dedupe.js 960 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 3.04 kB
packages/db/dist/esm/utils.js 927 B
packages/db/dist/esm/utils/array-utils.js 273 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 1.11 kB
packages/db/dist/esm/utils/cursor.js 457 B
packages/db/dist/esm/utils/index-optimization.js 2.39 kB
packages/db/dist/esm/utils/type-guards.js 157 B
packages/db/dist/esm/utils/uuid.js 449 B
packages/db/dist/esm/virtual-props.js 360 B

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

@github-actions

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 3.81 kB

ℹ️ View Unchanged
Filename Size
packages/react-db/dist/esm/index.js 249 B
packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.32 kB
packages/react-db/dist/esm/useLiveQuery.js 924 B
packages/react-db/dist/esm/useLiveQueryEffect.js 355 B
packages/react-db/dist/esm/useLiveSuspenseQuery.js 567 B
packages/react-db/dist/esm/usePacedMutations.js 401 B

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

@kevin-dp kevin-dp marked this pull request as ready for review July 15, 2026 13:07
kevin-dp and others added 2 commits July 15, 2026 15:19
…match warn

Addresses review of the window-controller extraction:

- pageSize/initialPageParam are now part of the controller-recreation check, so
  changing them at runtime re-windows and re-slices (the old hook had them in
  its effect/memo deps; the first controller draft baked them in at creation).
- Restore the one-time console.warn when a pre-created collection's existing
  window differs from the first page the hook enforces (dropped in the rewrite).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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