Skip to content

Commit

Permalink
Fix multi tab persistence issue (#8247)
Browse files Browse the repository at this point in the history
  • Loading branch information
milaGGL authored May 14, 2024
1 parent 9cbb184 commit 2ce9569
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .changeset/nine-rings-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@firebase/firestore': patch
'firebase': patch
---

Fix multi-tab persistence raising empty snapshot issue
3 changes: 2 additions & 1 deletion packages/firestore/src/core/sync_engine_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1095,9 +1095,10 @@ export async function syncEngineEmitNewSnapsAndNotifyLocalStore(
// secondary clients to update query state.
if (viewSnapshot || remoteEvent) {
if (syncEngineImpl.isPrimaryClient) {
const isCurrent = viewSnapshot && !viewSnapshot.fromCache;
syncEngineImpl.sharedClientState.updateQueryState(
queryView.targetId,
viewSnapshot?.fromCache ? 'not-current' : 'current'
isCurrent ? 'current' : 'not-current'
);
}
}
Expand Down
40 changes: 39 additions & 1 deletion packages/firestore/test/unit/specs/query_spec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { Document } from '../../../src/model/document';
import { doc, filter, query } from '../../util/helpers';

import { describeSpec, specTest } from './describe_spec';
import { spec, SpecBuilder } from './spec_builder';
import { client, spec, SpecBuilder } from './spec_builder';

// Helper to seed the cache with the specified docs by listening to each one.
function specWithCachedDocs(...docs: Document[]): SpecBuilder {
Expand Down Expand Up @@ -136,4 +136,42 @@ describeSpec('Queries:', [], () => {
);
}
);

specTest(
'Queries in different tabs will not interfere',
['multi-client'],
() => {
const query1 = query('collection', filter('key', '==', 'a'));
const query2 = query('collection', filter('key', '==', 'b'));
const docA = doc('collection/a', 1000, { key: 'a' });
const docB = doc('collection/b', 1000, { key: 'b' });

return (
client(0)
.becomeVisible()
// Listen to the first query in the primary client
.expectPrimaryState(true)
.userListens(query1)
.watchAcks(query1)
.watchSends({ affects: [query1] }, docA)

// Listen to different query in the secondary client
.client(1)
.userListens(query2)

.client(0)
.expectListen(query2)
.watchCurrents(query1, 'resume-token-1000')
// Receive global snapshot before the second query is acknowledged
.watchSnapshots(1000)
.expectEvents(query1, { added: [docA] })
// This should not trigger empty snapshot for second query(bugged behavior)
.client(1)
.client(0)
.watchAcksFull(query2, 2000, docB)
.client(1)
.expectEvents(query2, { added: [docB] })
);
}
);
});

0 comments on commit 2ce9569

Please sign in to comment.