…ations (issue #1017)
When a sync transaction commits while there's a pending optimistic mutation,
the sync data was being queued but not visible to derived collections (live
queries). This caused synced data to be invisible until the optimistic
mutation completed.
Root cause: commitPendingTransactions() was designed to delay processing
sync transactions while there's a persisting user transaction, to avoid
complex reconciliation. However, this also prevented change events from
being emitted to subscribers, making the synced data invisible to live
query collections that depend on those events.
Fix: Add an else branch that emits change events for committed sync
operations without modifying syncedData. This allows:
1. The source collection's state (syncedData) to remain unchanged during
the persisting transaction (preserving existing behavior)
2. Subscribers (including live queries) to receive events about the new
synced data, making it visible immediately
The fix skips emitting events for keys that have pending optimistic
mutations (optimisticUpserts/optimisticDeletes) to avoid conflicts.
When the persisting transaction completes, the normal reconciliation
flow will handle those keys.
Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Fixes the issue where synced data from a source collection does not appear in a derived (live query) collection while there is a pending optimistic mutation.
Root Cause
When a sync transaction commits while there's a persisting user transaction (optimistic mutation),
commitPendingTransactions()was designed to delay processing the sync transaction. However, this also prevented change events from being emitted to subscribers, making the synced data invisible to live query collections.The issue manifests in applications that use optimistic updates with live queries - synced data arriving during a pending mutation becomes invisible until the mutation completes.
The Fix
Add an
elsebranch tocommitPendingTransactions()that emits change events for committed sync operations without modifyingsyncedData. This approach:state(syncedData) remains unchanged during the persisting transaction, which is the expected behavior per existing testsoptimisticUpserts/optimisticDeletes)When the persisting transaction completes, the normal reconciliation flow processes the queued sync transactions and updates
syncedData.How to Test
The test creates:
createLiveQueryCollectionRelated
🤖 Generated with Claude Code