Skip to content

Conversation

@KyleAMathews
Copy link
Collaborator

Fix a race condition in WebLocksLeader where transactions could be replayed twice on page load. The issue occurred because:

  1. requestLeadership() returned true immediately when lock was available
  2. But notifyLeadershipChange(true) was called asynchronously when the fire-and-forget navigator.locks.request() actually acquired the lock
  3. This caused loadAndReplayTransactions() to be called twice - once manually and once via the callback

The fix sets isLeaderState = true synchronously when we know the lock is available, so the async notifyLeadershipChange(true) doesn't trigger the callback again (the guard checks isLeaderState !== isLeader).

Reported by Toba on Discord.

🎯 Changes

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

@changeset-bot
Copy link

changeset-bot bot commented Dec 18, 2025

🦋 Changeset detected

Latest commit: 350d887

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

This PR includes changesets to release 1 package
Name Type
@tanstack/offline-transactions 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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 18, 2025

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-ivm

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

@tanstack/electric-db-collection

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

@tanstack/offline-transactions

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

@tanstack/powersync-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: 350d887

@github-actions
Copy link
Contributor

github-actions bot commented Dec 18, 2025

Size Change: 0 B

Total Size: 89.4 kB

ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 999 B
./packages/db/dist/esm/collection/events.js 388 B
./packages/db/dist/esm/collection/index.js 3.24 kB
./packages/db/dist/esm/collection/indexes.js 1.1 kB
./packages/db/dist/esm/collection/lifecycle.js 1.67 kB
./packages/db/dist/esm/collection/mutations.js 2.34 kB
./packages/db/dist/esm/collection/state.js 3.46 kB
./packages/db/dist/esm/collection/subscription.js 3.54 kB
./packages/db/dist/esm/collection/sync.js 2.38 kB
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.27 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/index.js 2.68 kB
./packages/db/dist/esm/indexes/auto-index.js 742 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 1.93 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.1 kB
./packages/db/dist/esm/indexes/reverse-index.js 513 B
./packages/db/dist/esm/local-only.js 837 B
./packages/db/dist/esm/local-storage.js 2.1 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 733 B
./packages/db/dist/esm/query/builder/index.js 3.96 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 917 B
./packages/db/dist/esm/query/compiler/evaluators.js 1.35 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 1.8 kB
./packages/db/dist/esm/query/compiler/index.js 1.96 kB
./packages/db/dist/esm/query/compiler/joins.js 2 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.46 kB
./packages/db/dist/esm/query/compiler/select.js 1.07 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 673 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 5.33 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 1.9 kB
./packages/db/dist/esm/query/live/internal.js 130 B
./packages/db/dist/esm/query/optimizer.js 2.56 kB
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB
./packages/db/dist/esm/query/subset-dedupe.js 921 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 2.9 kB
./packages/db/dist/esm/utils.js 881 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 852 B
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.51 kB
./packages/db/dist/esm/utils/type-guards.js 157 B

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

@github-actions
Copy link
Contributor

github-actions bot commented Dec 18, 2025

Size Change: 0 B

Total Size: 3.35 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 225 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.17 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.12 kB
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 431 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

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

@KyleAMathews KyleAMathews force-pushed the claude/investigate-discord-bug-TD4bH branch 3 times, most recently from 4171209 to 414db19 Compare December 19, 2025 15:45
…nitialization

Fix a race condition in WebLocksLeader where transactions could be
replayed twice on page load. The issue occurred because:

1. requestLeadership() returned true immediately when lock was available
2. But notifyLeadershipChange(true) was called asynchronously when the
   fire-and-forget navigator.locks.request() actually acquired the lock
3. This caused loadAndReplayTransactions() to be called twice - once
   manually and once via the callback

The fix has two parts:
1. Set WebLocksLeader.isLeaderState = true synchronously when we know
   the lock is available, so the async notifyLeadershipChange(true)
   doesn't trigger the callback again
2. Set OfflineExecutor.isLeaderState based on requestLeadership() return
   value, since we can no longer rely on the callback to set it

Reported by Toba on Discord.
@KyleAMathews KyleAMathews force-pushed the claude/investigate-discord-bug-TD4bH branch from 414db19 to 350d887 Compare December 19, 2025 15:55
@KyleAMathews KyleAMathews moved this to Ready for review in 1.0.0 release Jan 6, 2026
@kevin-dp
Copy link
Contributor

kevin-dp commented Jan 7, 2026

Fixes #921

@kevin-dp kevin-dp linked an issue Jan 7, 2026 that may be closed by this pull request
@kevin-dp kevin-dp merged commit 65336df into main Jan 7, 2026
7 checks passed
@kevin-dp kevin-dp deleted the claude/investigate-discord-bug-TD4bH branch January 7, 2026 15:33
@kevin-dp kevin-dp removed this from 1.0.0 release Jan 7, 2026
@github-actions github-actions bot mentioned this pull request Jan 6, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 7, 2026

🎉 This PR has been released!

Thank you for your contribution!

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.

Offline transactions applied twice on reload

4 participants