Skip to content

Commit

Permalink
Fix b/249494921: Secondary Tab time travels with document deletes (#6635
Browse files Browse the repository at this point in the history
)
  • Loading branch information
wu-hui authored Sep 28, 2022
1 parent fdd4ab4 commit a7255a2
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
10 changes: 8 additions & 2 deletions packages/firestore/src/core/sync_engine_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1021,13 +1021,19 @@ export async function syncEngineEmitNewSnapsAndNotifyLocalStore(
syncEngineImpl
.applyDocChanges(queryView, changes, remoteEvent)
.then(viewSnapshot => {
if (viewSnapshot) {
// If there are changes, or we are handling a global snapshot, notify
// secondary clients to update query state.
if (viewSnapshot || remoteEvent) {
if (syncEngineImpl.isPrimaryClient) {
syncEngineImpl.sharedClientState.updateQueryState(
queryView.targetId,
viewSnapshot.fromCache ? 'not-current' : 'current'
viewSnapshot?.fromCache ? 'not-current' : 'current'
);
}
}

// Update views if there are actual changes.
if (!!viewSnapshot) {
newSnaps.push(viewSnapshot);
const docChanges = LocalViewChanges.fromSnapshot(
queryView.targetId,
Expand Down
54 changes: 54 additions & 0 deletions packages/firestore/test/unit/specs/listen_spec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,60 @@ describeSpec('Listens:', [], () => {
}
);

// Reproduces b/249494921.
specTest(
'Secondary client advances query state with global snapshot from primary',
['multi-client'],
() => {
const query1 = query('collection');
const docA = doc('collection/a', 1000, { key: '1' });
const docADeleted = deletedDoc('collection/a', 2000);
const docARecreated = doc('collection/a', 2000, {
key: '2'
}).setHasLocalMutations();

return (
client(0)
.becomeVisible()
.expectPrimaryState(true)
.userListens(query1)
.watchAcksFull(query1, 1000, docA)
.expectEvents(query1, { added: [docA] })
.userUnlistens(query1)
.watchRemoves(query1)
.client(1)
.userListens(query1)
.expectEvents(query1, { added: [docA], fromCache: true })
.client(0)
.expectListen(query1, { resumeToken: 'resume-token-1000' })
.watchAcksFull(query1, 1500, docA)
.client(1)
.expectEvents(query1, {})
.client(0)
.userDeletes('collection/a')
.client(1)
.expectEvents(query1, {
removed: [docA]
})
.client(0)
.writeAcks('collection/a', 2000)
.watchAcksFull(query1, 2000, docADeleted)
.client(1) // expects no event
.client(0)
.userSets('collection/a', { key: '2' })
.client(1)
// Without the fix for b/249494921, two snapshots will be raised: a first
// one as show below, and a second one with `docADeleted` because
// `client(1)` failed to advance its cursor in remote document cache, and
// read a stale document.
.expectEvents(query1, {
added: [docARecreated],
hasPendingWrites: true
})
);
}
);

specTest(
'Mirror queries from same secondary client',
['multi-client'],
Expand Down

0 comments on commit a7255a2

Please sign in to comment.