Skip to content

Conversation

samwillis
Copy link
Collaborator

@samwillis samwillis commented Oct 1, 2025

fixes #609

We had code in place that filtered out redundant change events from sync operations, but it failed to filter delete events, only filtering insert/update.

CI run with test failure showing the repo before the fix is applied: https://github.com/TanStack/db/actions/runs/18163302240/job/51698976831?pr=621

Copy link

changeset-bot bot commented Oct 1, 2025

🦋 Changeset detected

Latest commit: b41e365

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 1, 2025

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: b41e365

Copy link
Contributor

github-actions bot commented Oct 1, 2025

Size Change: +36 B (+0.05%)

Total Size: 74.1 kB

Filename Size Change
./packages/db/dist/esm/collection/state.js 3.81 kB +36 B (+0.95%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 958 B
./packages/db/dist/esm/collection/changes.js 1.01 kB
./packages/db/dist/esm/collection/events.js 683 B
./packages/db/dist/esm/collection/index.js 3.14 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.59 kB
./packages/db/dist/esm/collection/subscription.js 1.69 kB
./packages/db/dist/esm/collection/sync.js 1.32 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 745 B
./packages/db/dist/esm/indexes/base-index.js 605 B
./packages/db/dist/esm/indexes/btree-index.js 1.82 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.25 kB
./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.87 kB
./packages/db/dist/esm/query/builder/functions.js 615 B
./packages/db/dist/esm/query/builder/index.js 3.93 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 938 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.56 kB
./packages/db/dist/esm/query/compiler/expressions.js 631 B
./packages/db/dist/esm/query/compiler/group-by.js 2.11 kB
./packages/db/dist/esm/query/compiler/index.js 2.04 kB
./packages/db/dist/esm/query/compiler/joins.js 2.54 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.23 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.68 kB
./packages/db/dist/esm/query/live/collection-subscriber.js 1.91 kB
./packages/db/dist/esm/query/optimizer.js 3.1 kB
./packages/db/dist/esm/SortedMap.js 1.24 kB
./packages/db/dist/esm/transactions.js 3.03 kB
./packages/db/dist/esm/utils.js 943 B
./packages/db/dist/esm/utils/browser-polyfills.js 365 B
./packages/db/dist/esm/utils/btree.js 6.02 kB
./packages/db/dist/esm/utils/comparison.js 754 B
./packages/db/dist/esm/utils/index-optimization.js 1.62 kB

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

Copy link
Contributor

github-actions bot commented Oct 1, 2025

Size Change: 0 B

Total Size: 1.44 kB

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

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

@samwillis samwillis marked this pull request as ready for review October 1, 2025 13:18
completedOp.type === `delete` &&
previousVisibleValue !== undefined &&
newVisibleValue === undefined &&
deepEquals(completedOp.value, previousVisibleValue)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't love really that we do all these deepEquals — they're fairly expensive — but I suppose cheaper than the UI framework re-rendering the same bits of UI 🤷

Copy link
Collaborator

Choose a reason for hiding this comment

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

In this particular case, we don't actually need a deepEqual right? Since a delete is a delete is a delete. If the optimistic mutation got rid of it already, we can just immediately assume the synced delete is the same?

Copy link
Collaborator Author

@samwillis samwillis Oct 1, 2025

Choose a reason for hiding this comment

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

The deepEquals are not really about stoping re-renders, they are deduplicating events in the same batch that could result in an invalid state. This is particularly important when feeding into the d2 graph as aggregates could become wrong, or the multiplicity could and we then track inserts/deletes later incorrectly.

I agree, I would prefer not to have them, but I think we should approach that in a general redesign of this reconciliation process - I don't particularly like how it currently works.

In this particular case, we don't actually need a deepEqual right?
Maybe, but I don't really want to bet on it. It's still about removing duplicates and there could be multiple deletes for the same key in the same batch. We just want to ensure the state inside d2 is correct. I don't want to make an assumption, I would prefer to take a belt and braces at this point before we further refactor.

Do note that these deepEquals are only happening on optimistic mutations, not on every change that is synced, and not on every emitted initial state into the live query engine. As overhead it's tiny compared to the other things happening in D2.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do note that these deepEquals are only happening on optimistic mutations, not on every change that is synced

Ah ok, so very little generally 👍

@samwillis samwillis requested a review from KyleAMathews October 1, 2025 13:54
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.

:shipit:

@samwillis samwillis merged commit 05776f5 into main Oct 1, 2025
6 checks passed
@samwillis samwillis deleted the samwillis/fix-mutation-race branch October 1, 2025 14:00
@github-actions github-actions bot mentioned this pull request Oct 1, 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.

Sums are updated twice in live queries
2 participants