-
Notifications
You must be signed in to change notification settings - Fork 161
fix(db): track loadSubset promise for on-demand live queries #1192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
KyleAMathews
wants to merge
6
commits into
main
Choose a base branch
from
is-ready-redux
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+159
−19
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
When a live query without orderBy/limit subscribes to an on-demand collection, the subscription was passing includeInitialState: true to subscribeChanges, which internally called requestSnapshot with trackLoadSubsetPromise: false. This prevented the subscription status from transitioning to 'loadingSubset', causing the live query to be marked ready before data actually loaded. The fix changes subscribeToMatchingChanges to manually call requestSnapshot() after creating the subscription (with default tracking enabled), ensuring the loadSubset promise is properly tracked and the live query waits for data before becoming ready. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This follow-up fix addresses edge cases that caused tests to fail after the initial isReady fix: 1. lifecycle.ts: Call pending onFirstReady callbacks during cleanup - Prevents preload() promises from hanging when cleanup happens - Ensures clean termination of pending preload operations 2. query.ts: Add fallback cache checks in createQueryFromOpts - Check QueryClient cache when observer state is out of sync - Handle cases where observer was deleted but data is still cached - Prevents hangs during cleanup/recreate cycles 3. Test updates: - Updated where clause tests to use synchronous loadSubset - These tests verify where clause passing, not async loading behavior Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 3d6e48b The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
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 |
More templates
@tanstack/angular-db
@tanstack/db
@tanstack/db-ivm
@tanstack/electric-db-collection
@tanstack/offline-transactions
@tanstack/powersync-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
Contributor
|
Size Change: +258 B (+0.28%) Total Size: 91.2 kB
ℹ️ View Unchanged
|
Contributor
|
Size Change: 0 B Total Size: 3.7 kB ℹ️ View Unchanged
|
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fca9084 to
46d4ec5
Compare
- Fix potential memory leak in trackCollectionLoading by registering cleanup callback for early unsubscribe scenarios - Add error handling for onFirstReady callbacks during cleanup to ensure all callbacks are attempted even if one throws Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, when multiple live queries subscribed to the same source collection, only the first would correctly track loading state due to the `!wasLoadingBefore` guard. This caused subsequent live queries to incorrectly report `isReady` before data finished loading. The fix removes this guard since each live query needs its own loading state tracking regardless of whether another query already triggered loading. Also adds a regression test for this scenario. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Verified this locally. Working great! 👍 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Fixes
isReadytracking for on-demand live queries withoutorderBy. Previously, non-ordered live queries usingsyncMode: 'on-demand'were incorrectly marked as ready before data finished loading. This also fixespreload()promises hanging when cleanup occurs before the collection becomes ready.Root Cause
For non-ordered live queries,
subscribeChangesis called withincludeInitialState: true, which internally callsrequestSnapshot({ trackLoadSubsetPromise: false }). This disables the subscription's status tracking—the subscription never transitions toloadingSubsetstatus, so the live query'sisReadystayed true during loading.This only affected non-ordered queries because ordered queries (with
limit/offset) use a different code path (subscribeToOrderedChanges) that callsrequestSnapshot()with default tracking enabled.Approach
The fix couldn't simply change
trackLoadSubsetPromisetotruebecause that breaks truncate handling (must-refetch scenarios). The truncate buffering logic depends on the existing status behavior.Instead, the fix:
Tracks loading at the collection level (
collection-subscriber.ts): After subscribing, checks if the source collection'sisLoadingSubsetchanged from false to true. If so, listens for theloadingSubset:changeevent and tracks a promise on the live query collection forisReady. Includes cleanup registration to prevent memory leaks if unsubscribed early.Calls onFirstReady callbacks during cleanup (
lifecycle.ts): Ensurespreload()promises resolve instead of hanging when cleanup occurs before the collection becomes ready. Includes try-catch error handling to ensure all callbacks are attempted.Adds QueryClient cache fallbacks (
query.ts): Handles edge cases where observer state may be stale after unsubscribe/resubscribe cycles.Key Invariants
isReadymust returnfalsewhileloadSubsetis in progresspreload()must always resolve (either when ready OR during cleanup)Non-goals
trackLoadSubsetPromisebehaviorVerification
All tests pass:
Files Changed
packages/db/src/query/live/collection-subscriber.ts- Track collection loading state with cleanuppackages/db/src/collection/lifecycle.ts- Call callbacks during cleanup with error handlingpackages/query-db-collection/src/query.ts- Add QueryClient cache fallback checks🤖 Generated with Claude Code