Skip to content

Conversation

samwillis
Copy link
Collaborator

@samwillis samwillis commented Oct 6, 2025

fixes #645

The original reproduction from that issue updated to the preview package from this PR: https://stackblitz.com/edit/tanstack-db-init-jm98exso?file=src%2FApp.tsx

Summary

The bug was in the capturePreSyncVisibleState() method in state.ts. Here's what was happening:

The Race Condition:

  1. When the first transaction (T1) completed, capturePreSyncVisibleState() captured the visible state for key "0" (with optimistic data)
  2. Then recomputeOptimisticState() cleared T1's optimistic state
  3. commitPendingTransactions() couldn't run yet because T2 was still persisting
  4. When T2 completed, capturePreSyncVisibleState() was called again and cleared all previous captures with this.preSyncVisibleState.clear()
  5. At this point, key "0" was no longer in the optimistic state (cleared when T1 completed), so it wasn't recaptured
  6. When commitPendingTransactions() finally ran, it had no previousVisibleValue for key "0", causing it to emit INSERT instead of UPDATE

The Fix:
I modified capturePreSyncVisibleState() to:

  1. Remove the this.preSyncVisibleState.clear() call to preserve previously captured state
  2. Add a check if (!this.preSyncVisibleState.has(key)) before capturing to avoid overwriting earlier captures

This ensures that when transactions complete at different times (due to async delays in onInsert), each key's visible state is captured at the correct moment - when its corresponding transaction completes and before its optimistic state is cleared. The state is then preserved until all sync operations can be committed together.

Copy link

changeset-bot bot commented Oct 6, 2025

🦋 Changeset detected

Latest commit: 9f0f852

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

This PR includes changesets to release 12 packages
Name Type
@tanstack/db Patch
@tanstack/angular-db Patch
@tanstack/electric-db-collection Patch
@tanstack/query-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
todos Patch
@tanstack/db-example-react-todo 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

Copy link

pkg-pr-new bot commented Oct 6, 2025

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: 9f0f852

@samwillis samwillis requested a review from KyleAMathews October 6, 2025 19:20
Copy link
Contributor

github-actions bot commented Oct 6, 2025

Size Change: +7 B (+0.01%)

Total Size: 75.2 kB

Filename Size Change
./packages/db/dist/esm/collection/state.js 3.82 kB +7 B (+0.18%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 943 B
./packages/db/dist/esm/collection/changes.js 1.01 kB
./packages/db/dist/esm/collection/events.js 660 B
./packages/db/dist/esm/collection/index.js 3.18 kB
./packages/db/dist/esm/collection/indexes.js 1.16 kB
./packages/db/dist/esm/collection/lifecycle.js 1.8 kB
./packages/db/dist/esm/collection/mutations.js 2.5 kB
./packages/db/dist/esm/collection/subscription.js 1.65 kB
./packages/db/dist/esm/collection/sync.js 1.42 kB
./packages/db/dist/esm/deferred.js 230 B
./packages/db/dist/esm/errors.js 3.1 kB
./packages/db/dist/esm/index.js 1.56 kB
./packages/db/dist/esm/indexes/auto-index.js 806 B
./packages/db/dist/esm/indexes/base-index.js 835 B
./packages/db/dist/esm/indexes/btree-index.js 2 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.21 kB
./packages/db/dist/esm/indexes/reverse-index.js 577 B
./packages/db/dist/esm/local-only.js 827 B
./packages/db/dist/esm/local-storage.js 2.02 kB
./packages/db/dist/esm/optimistic-action.js 294 B
./packages/db/dist/esm/proxy.js 3.86 kB
./packages/db/dist/esm/query/builder/functions.js 615 B
./packages/db/dist/esm/query/builder/index.js 4.04 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 938 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.55 kB
./packages/db/dist/esm/query/compiler/expressions.js 631 B
./packages/db/dist/esm/query/compiler/group-by.js 2.04 kB
./packages/db/dist/esm/query/compiler/index.js 2.04 kB
./packages/db/dist/esm/query/compiler/joins.js 2.52 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.21 kB
./packages/db/dist/esm/query/compiler/select.js 1.28 kB
./packages/db/dist/esm/query/ir.js 785 B
./packages/db/dist/esm/query/live-query-collection.js 340 B
./packages/db/dist/esm/query/live/collection-config-builder.js 2.69 kB
./packages/db/dist/esm/query/live/collection-subscriber.js 1.86 kB
./packages/db/dist/esm/query/optimizer.js 3.08 kB
./packages/db/dist/esm/SortedMap.js 1.24 kB
./packages/db/dist/esm/transactions.js 3 kB
./packages/db/dist/esm/utils.js 1.01 kB
./packages/db/dist/esm/utils/browser-polyfills.js 365 B
./packages/db/dist/esm/utils/btree.js 6.01 kB
./packages/db/dist/esm/utils/comparison.js 754 B
./packages/db/dist/esm/utils/index-optimization.js 1.73 kB

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

Copy link
Contributor

github-actions bot commented Oct 6, 2025

Size Change: 0 B

Total Size: 1.47 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 152 B
./packages/react-db/dist/esm/useLiveQuery.js 1.32 kB

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

Copy link
Collaborator

@KyleAMathews KyleAMathews left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great!

@obeattie
Copy link
Contributor

obeattie commented Oct 6, 2025

Just tried this in my codebase and it definitely fixes the issue I was seeing. You guys rock.

@samwillis samwillis merged commit 7556fb6 into main Oct 6, 2025
6 checks passed
@samwillis samwillis deleted the samwillis/subscribe-changes-duplicate-insert branch October 6, 2025 20:52
@github-actions github-actions bot mentioned this pull request Oct 6, 2025
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.

Queries break collection sync when multiple optimistic updates are queued
3 participants