fix: reconcile duplicate live query child inserts#1600
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthrough
ChangesSync duplicate-key fix and child include insert/update improvements
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
More templates
@tanstack/angular-db
@tanstack/browser-db-sqlite-persistence
@tanstack/capacitor-db-sqlite-persistence
@tanstack/cloudflare-durable-objects-db-sqlite-persistence
@tanstack/db
@tanstack/db-ivm
@tanstack/db-sqlite-persistence-core
@tanstack/electric-db-collection
@tanstack/electron-db-sqlite-persistence
@tanstack/expo-db-sqlite-persistence
@tanstack/node-db-sqlite-persistence
@tanstack/offline-transactions
@tanstack/powersync-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/react-native-db-sqlite-persistence
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/tauri-db-sqlite-persistence
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
|
Size Change: +25 B (+0.02%) Total Size: 123 kB 📦 View Changed
ℹ️ View Unchanged
|
|
Size Change: 0 B Total Size: 4.24 kB ℹ️ View Unchanged
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@packages/db/tests/query/includes.test.ts`:
- Around line 617-621: Replace the fixed `setTimeout(resolve, 10)` sleep in this
test with a condition-based wait that directly polls for the expected child
items snapshot. Instead of sleeping for a fixed duration, create a polling loop
that repeatedly checks if the childItems from the product matches the expected
array, and only resolve the promise when the condition is satisfied. This
eliminates the timing sensitivity and prevents test flakiness when async
propagation is slower.
In `@packages/query-db-collection/tests/query.test.ts`:
- Around line 292-298: The regression assertion in the vi.waitFor() callback is
validating products.get() directly, which doesn't test if the includes-child
reconciliation is working properly and can miss duplicate-insert bugs in the
join logic. Change the assertion to validate the included product collection
from the live query row instead, so the test actually guards against regression
in the child include reconciliation. Modify the expect statement inside
vi.waitFor() to access the product data through the included child collection
relationship rather than through direct products.get() access.
🪄 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: 2c8e03e7-4488-41b6-bd03-dd6d99f54b83
📒 Files selected for processing (4)
packages/db/src/query/live/collection-config-builder.tspackages/db/tests/collection.test.tspackages/db/tests/query/includes.test.tspackages/query-db-collection/tests/query.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/db/tests/collection.test.ts
|
Installed : https://pkg.pr.new/@tanstack/react-db@c183272 This seems to done the trick i no longer see the error in the console and updates are working again thanks for the quick response!! |
Fix live-query includes reconciliation so
.update()flows that re-emit an existing joined child row update the internal child collection instead of attempting a duplicate insert.User-visible impact: updating a
queryCollectionOptionssource used in a live query with joined/included child rows no longer crashes with either the secondaryLIVE_QUERY_INTERNALTypeErroror the underlying duplicate child insert error.Root Cause
The user action is
.update(), but that update triggers live-query graph reconciliation. During reconciliation,flushIncludesStatewrites changes into internal child collections such as:From that internal collection's perspective, a derived/joined row can be emitted as an
inserteven though the user operation was an update. When the child collection already contained that key, sync correctly rejected the duplicate insert:There was also a secondary issue in the duplicate-key error path: generic/internal collection configs do not necessarily have live-query internals in
config.utils, butsync.tsassumed they did while constructingDuplicateKeySyncErrorcontext.Approach
The fix has two parts:
In
flushIncludesState, compute whether the internal child collection already has the child key before writing an insert-only child change. If the child already exists, write an internalupdateinstead of aninsert.In the duplicate-key sync error path, guard optional
config.utilsbefore readingLIVE_QUERY_INTERNAL, preserving enhanced context when present and defaulting the flags when absent.Key Invariants
LIVE_QUERY_INTERNALis present.utilsmust not throw a secondaryTypeErrorwhile constructing duplicate-key errors.Non-goals
.update()semantics.Trade-offs
The targeted fix keeps reconciliation local to the internal child collection write decision. A broader alternative would be changing upstream D2/includes change classification, but the child collection is the place with direct knowledge of whether a given child key is already materialized.
Verification
CI is green for PR #1600, including:
Files changed
packages/db/src/collection/sync.tsconfig.utilsbefore readingLIVE_QUERY_INTERNAL.packages/db/src/query/live/collection-config-builder.tspackages/db/tests/collection.test.tsutils.packages/db/tests/query/includes.test.tspackages/query-db-collection/tests/query.test.ts.changeset/fix-sync-duplicate-key-utils.md@tanstack/db.Fixes #1599
Summary by CodeRabbit
Bug Fixes
Tests