TanStackT
TanStack4w ago
11 replies
awake-maroon

[SOLVED] Double replay of offline transactions on initialization

Still experimenting with offline transactions. I think there's a race condition when a new or refreshed page is loaded and the offline executor replays pending transactions. It does not occur when offline/online state changes within the same page.

In OfflineExecutor.ts:initialize():
https://github.com/TanStack/db/blob/main/packages/offline-transactions/src/OfflineExecutor.ts
const isLeader = await this.leaderElection.requestLeadership()
this.setupEventListeners()  // Registers callback
if (isLeader) {
  await this.loadAndReplayTransactions()
}


The problem:
1. requestLeadership() launches lock acquisition but returns immediately before the lock is actually acquired
2. setupEventListeners() registers the onLeadershipChange callback
3. First replay: Manual call at line 274 (inside the if block)
4. A few milliseconds later: lock acquired → notifyLeadershipChange(true) fires
5. Second replay: Callback executes loadAndReplayTransactions() again

In the console, I can see duplicate calls of the mutations with the same idempotencyKey.

Potential fix:
Remove the manual replay:
if (isLeader) {
  await this.loadAndReplayTransactions() 
}


Keep only setupEventListeners(), which might be sufficient since loadAndReplayTransactions() is automatically called when leadership is acquired through the callback.

What do you guys think?
GitHub
The reactive client store for your API. Contribute to TanStack/db development by creating an account on GitHub.
db/packages/offline-transactions/src/OfflineExecutor.ts at main · ...
Was this page helpful?