From 3b2f2c776001bff6f07604b45693439632384144 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:03:40 -0400 Subject: [PATCH 1/9] initial code fix --- packages/firestore/src/core/sync_engine_impl.ts | 5 ++++- packages/firestore/src/core/view.ts | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/firestore/src/core/sync_engine_impl.ts b/packages/firestore/src/core/sync_engine_impl.ts index 60a36d0dcaf..fee5d751c8c 100644 --- a/packages/firestore/src/core/sync_engine_impl.ts +++ b/packages/firestore/src/core/sync_engine_impl.ts @@ -1081,10 +1081,13 @@ async function applyDocChanges( const targetChange = remoteEvent && remoteEvent.targetChanges.get(queryView.targetId); + const isPendingForRequeryResult = + remoteEvent && remoteEvent.targetMismatches.get(queryView.targetId) != null; const viewChange = queryView.view.applyChanges( viewDocChanges, /* updateLimboDocuments= */ syncEngineImpl.isPrimaryClient, - targetChange + targetChange, + isPendingForRequeryResult ); updateTrackedLimbos( syncEngineImpl, diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index de66d883ac3..73599a142c4 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -273,6 +273,8 @@ export class View { * @param docChanges - The set of changes to make to the view's docs. * @param updateLimboDocuments - Whether to update limbo documents based on * this change. + * @param isPendingForRequeryResult - Whether the target is pending to run a full + * re-query due to existence filter mismatch. * @param targetChange - A target change to apply for computing limbo docs and * sync state. * @returns A new ViewChange with the given docs, changes, and sync state. @@ -281,7 +283,8 @@ export class View { applyChanges( docChanges: ViewDocumentChanges, updateLimboDocuments: boolean, - targetChange?: TargetChange + targetChange?: TargetChange, + isPendingForRequeryResult: boolean = false, ): ViewChange { debugAssert( !docChanges.needsRefill, @@ -300,10 +303,16 @@ export class View { }); this.applyTargetChange(targetChange); - const limboChanges = updateLimboDocuments + const limboChanges = !isPendingForRequeryResult && updateLimboDocuments ? this.updateLimboDocuments() : []; - const synced = this.limboDocuments.size === 0 && this.current; + + // We are at synced state if there is no limbo docs are waiting to be resolved, view is current + // with the backend, and the query is not pending for full re-query result due to existence + // filter mismatch. + const synced = + this.limboDocuments.size === 0 && this.current && !isPendingForRequeryResult; + const newSyncState = synced ? SyncState.Synced : SyncState.Local; const syncStateChanged = newSyncState !== this.syncState; this.syncState = newSyncState; From 78d92d247fc183ec410295953ce026c6201e97a1 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:32:35 -0400 Subject: [PATCH 2/9] remove parameter default value --- packages/firestore/src/core/view.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index 73599a142c4..b0ecfe0769c 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -284,7 +284,7 @@ export class View { docChanges: ViewDocumentChanges, updateLimboDocuments: boolean, targetChange?: TargetChange, - isPendingForRequeryResult: boolean = false, + isPendingForRequeryResult?: boolean ): ViewChange { debugAssert( !docChanges.needsRefill, @@ -303,15 +303,18 @@ export class View { }); this.applyTargetChange(targetChange); - const limboChanges = !isPendingForRequeryResult && updateLimboDocuments - ? this.updateLimboDocuments() - : []; + const limboChanges = + !isPendingForRequeryResult && updateLimboDocuments + ? this.updateLimboDocuments() + : []; // We are at synced state if there is no limbo docs are waiting to be resolved, view is current // with the backend, and the query is not pending for full re-query result due to existence // filter mismatch. - const synced = - this.limboDocuments.size === 0 && this.current && !isPendingForRequeryResult; + const synced = + this.limboDocuments.size === 0 && + this.current && + !isPendingForRequeryResult; const newSyncState = synced ? SyncState.Synced : SyncState.Local; const syncStateChanged = newSyncState !== this.syncState; From 49f3a95b2ee7cb6c05ca7df2121486b419168b40 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:47:45 -0400 Subject: [PATCH 3/9] update spec tests --- packages/firestore/test/unit/specs/limbo_spec.test.ts | 4 ++-- packages/firestore/test/unit/specs/limit_spec.test.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/firestore/test/unit/specs/limbo_spec.test.ts b/packages/firestore/test/unit/specs/limbo_spec.test.ts index 5d1c978b101..837b9def54b 100644 --- a/packages/firestore/test/unit/specs/limbo_spec.test.ts +++ b/packages/firestore/test/unit/specs/limbo_spec.test.ts @@ -889,6 +889,7 @@ describeSpec('Limbo Documents:', [], () => { // to just send the docBs with an existence filter with a count of 3. .watchSends({ affects: [query1] }, docB1, docB2, docB3) .watchFilters([query1], [docB1.key, docB2.key, docB3.key]) + .watchCurrents(query1, 'resume-token-1001') .watchSnapshots(1001) .expectEvents(query1, { added: [docB1, docB2, docB3], @@ -968,6 +969,7 @@ describeSpec('Limbo Documents:', [], () => { [docB1.key, docB2.key, docB3.key], bloomFilterProto ) + .watchCurrents(query1, 'resume-token-1001') .watchSnapshots(1001) .expectEvents(query1, { added: [docB1, docB2, docB3], @@ -978,8 +980,6 @@ describeSpec('Limbo Documents:', [], () => { // existence filter mismatch. Bloom filter checks membership of the // docs, and filters out docAs, while docBs returns true. Number of // existing docs matches the expected count, so skip the re-query. - .watchCurrents(query1, 'resume-token-1002') - .watchSnapshots(1002) // The docAs are now in limbo; the client begins limbo resolution. .expectLimboDocs(docA1.key, docA2.key) .expectEnqueuedLimboDocs(docA3.key) diff --git a/packages/firestore/test/unit/specs/limit_spec.test.ts b/packages/firestore/test/unit/specs/limit_spec.test.ts index bff90c4a324..4788bd4e93d 100644 --- a/packages/firestore/test/unit/specs/limit_spec.test.ts +++ b/packages/firestore/test/unit/specs/limit_spec.test.ts @@ -343,6 +343,7 @@ describeSpec('Limits:', [], () => { // out of sync. .watchSends({ affects: [limitQuery] }, secondDocument) .watchFilters([limitQuery], [secondDocument.key]) + .watchCurrents(limitQuery, 'resume-token-1004') .watchSnapshots(1004) .expectActiveTargets({ query: limitQuery, From b41f5286bd1905ea015117efdb480d85751434e0 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:54:16 -0400 Subject: [PATCH 4/9] rename the flag --- packages/firestore/src/core/sync_engine_impl.ts | 4 ++-- packages/firestore/src/core/view.ts | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/firestore/src/core/sync_engine_impl.ts b/packages/firestore/src/core/sync_engine_impl.ts index fee5d751c8c..2e994f6436e 100644 --- a/packages/firestore/src/core/sync_engine_impl.ts +++ b/packages/firestore/src/core/sync_engine_impl.ts @@ -1081,13 +1081,13 @@ async function applyDocChanges( const targetChange = remoteEvent && remoteEvent.targetChanges.get(queryView.targetId); - const isPendingForRequeryResult = + const waitForRequeryResult = remoteEvent && remoteEvent.targetMismatches.get(queryView.targetId) != null; const viewChange = queryView.view.applyChanges( viewDocChanges, /* updateLimboDocuments= */ syncEngineImpl.isPrimaryClient, targetChange, - isPendingForRequeryResult + waitForRequeryResult ); updateTrackedLimbos( syncEngineImpl, diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index b0ecfe0769c..411b0e79985 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -273,7 +273,7 @@ export class View { * @param docChanges - The set of changes to make to the view's docs. * @param updateLimboDocuments - Whether to update limbo documents based on * this change. - * @param isPendingForRequeryResult - Whether the target is pending to run a full + * @param waitForRequeryResult - Whether the target is pending to run a full * re-query due to existence filter mismatch. * @param targetChange - A target change to apply for computing limbo docs and * sync state. @@ -284,7 +284,7 @@ export class View { docChanges: ViewDocumentChanges, updateLimboDocuments: boolean, targetChange?: TargetChange, - isPendingForRequeryResult?: boolean + waitForRequeryResult?: boolean ): ViewChange { debugAssert( !docChanges.needsRefill, @@ -304,7 +304,7 @@ export class View { this.applyTargetChange(targetChange); const limboChanges = - !isPendingForRequeryResult && updateLimboDocuments + !waitForRequeryResult && updateLimboDocuments ? this.updateLimboDocuments() : []; @@ -312,9 +312,7 @@ export class View { // with the backend, and the query is not pending for full re-query result due to existence // filter mismatch. const synced = - this.limboDocuments.size === 0 && - this.current && - !isPendingForRequeryResult; + this.limboDocuments.size === 0 && this.current && !waitForRequeryResult; const newSyncState = synced ? SyncState.Synced : SyncState.Local; const syncStateChanged = newSyncState !== this.syncState; From c2e6aaa806b9c64bc0a65b5637f2650d496d1e66 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:43:23 -0400 Subject: [PATCH 5/9] format code --- packages/firestore/src/core/view.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index 411b0e79985..8897d33abc9 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -273,10 +273,10 @@ export class View { * @param docChanges - The set of changes to make to the view's docs. * @param updateLimboDocuments - Whether to update limbo documents based on * this change. - * @param waitForRequeryResult - Whether the target is pending to run a full - * re-query due to existence filter mismatch. * @param targetChange - A target change to apply for computing limbo docs and * sync state. + * @param waitForRequeryResult - Whether the target is pending to run a full + * re-query due to existence filter mismatch. * @returns A new ViewChange with the given docs, changes, and sync state. */ // PORTING NOTE: The iOS/Android clients always compute limbo document changes. @@ -303,10 +303,9 @@ export class View { }); this.applyTargetChange(targetChange); - const limboChanges = - !waitForRequeryResult && updateLimboDocuments - ? this.updateLimboDocuments() - : []; + const limboChanges = updateLimboDocuments + ? this.updateLimboDocuments(waitForRequeryResult ?? false) + : []; // We are at synced state if there is no limbo docs are waiting to be resolved, view is current // with the backend, and the query is not pending for full re-query result due to existence @@ -413,9 +412,11 @@ export class View { } } - private updateLimboDocuments(): LimboDocumentChange[] { + private updateLimboDocuments( + waitForRequeryResult: boolean + ): LimboDocumentChange[] { // We can only determine limbo documents when we're in-sync with the server. - if (!this.current) { + if (waitForRequeryResult || !this.current) { return []; } From a0a933e29ba3da3bd8a883945be0bb07d91b1cfb Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Mon, 6 Nov 2023 17:17:50 -0500 Subject: [PATCH 6/9] Update limbo_spec.test.ts --- .../test/unit/specs/limbo_spec.test.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/packages/firestore/test/unit/specs/limbo_spec.test.ts b/packages/firestore/test/unit/specs/limbo_spec.test.ts index 837b9def54b..d048167fbfc 100644 --- a/packages/firestore/test/unit/specs/limbo_spec.test.ts +++ b/packages/firestore/test/unit/specs/limbo_spec.test.ts @@ -928,6 +928,48 @@ describeSpec('Limbo Documents:', [], () => { } ); + // Reproduce the bug in b/238823695 + specTest( + 'Limbo resolution should wait for full re-query result if there is an existence filter mismatch ', + [], + () => { + const query1 = query('collection'); + const docA = doc('collection/a', 1000, { v: 1 }); + const docB = doc('collection/b', 1000, { v: 2 }); + return ( + spec() + .userListens(query1) + .watchAcksFull(query1, 1000, docA, docB) + .expectEvents(query1, { added: [docA, docB] }) + // Simulate that the client loses network connection. + .disableNetwork() + .expectEvents(query1, { fromCache: true }) + .enableNetwork() + .restoreListen(query1, 'resume-token-1000') + .watchAcks(query1) + // DocB is deleted in the next sync. + .watchFilters([query1], [docA.key]) + // Bugged behavior: Missing watchCurrent here will move + // all the docs to limbo unnecessarily. + .watchCurrents(query1, 'resume-token-2000') + .watchSnapshots(2000) + .expectActiveTargets({ + query: query1, + resumeToken: '', + targetPurpose: TargetPurpose.ExistenceFilterMismatch + }) + .watchRemoves(query1) + .watchAcksFull(query1, 3000, docA) + // Only the deleted doc is moved to limbo after re-query result. + .expectLimboDocs(docB.key) + .ackLimbo(3000, deletedDoc('collection/b', 3000)) + .expectLimboDocs() + .expectEvents(query1, { + removed: [docB] + }) + ); + } + ); specTest( 'Limbo resolution throttling with bloom filter application', [], From d9276092f54bffca6fb1c527531202213a04c027 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:55:13 -0500 Subject: [PATCH 7/9] resolve comments --- .../firestore/src/core/firestore_client.ts | 2 +- .../firestore/src/core/sync_engine_impl.ts | 8 ++--- packages/firestore/src/core/view.ts | 35 ++++++++++--------- .../firestore/test/unit/core/view.test.ts | 8 ++--- .../test/unit/local/query_engine.test.ts | 2 +- .../test/unit/specs/limbo_spec.test.ts | 6 ++-- 6 files changed, 30 insertions(+), 31 deletions(-) diff --git a/packages/firestore/src/core/firestore_client.ts b/packages/firestore/src/core/firestore_client.ts index fc51133f312..d7819bd7905 100644 --- a/packages/firestore/src/core/firestore_client.ts +++ b/packages/firestore/src/core/firestore_client.ts @@ -729,7 +729,7 @@ async function executeQueryFromCache( const viewDocChanges = view.computeDocChanges(queryResult.documents); const viewChange = view.applyChanges( viewDocChanges, - /* updateLimboDocuments= */ false + /* limboResolutionEnabled= */ false ); result.resolve(viewChange.snapshot!); } catch (e) { diff --git a/packages/firestore/src/core/sync_engine_impl.ts b/packages/firestore/src/core/sync_engine_impl.ts index 2e994f6436e..18a1dc681f5 100644 --- a/packages/firestore/src/core/sync_engine_impl.ts +++ b/packages/firestore/src/core/sync_engine_impl.ts @@ -368,7 +368,7 @@ async function initializeViewAndComputeSnapshot( ); const viewChange = view.applyChanges( viewDocChanges, - /* updateLimboDocuments= */ syncEngineImpl.isPrimaryClient, + /* limboResolutionEnabled= */ syncEngineImpl.isPrimaryClient, synthesizedTargetChange ); updateTrackedLimbos(syncEngineImpl, targetId, viewChange.limboChanges); @@ -1081,13 +1081,13 @@ async function applyDocChanges( const targetChange = remoteEvent && remoteEvent.targetChanges.get(queryView.targetId); - const waitForRequeryResult = + const targetIsPendingReset = remoteEvent && remoteEvent.targetMismatches.get(queryView.targetId) != null; const viewChange = queryView.view.applyChanges( viewDocChanges, - /* updateLimboDocuments= */ syncEngineImpl.isPrimaryClient, + /* limboResolutionEnabled= */ syncEngineImpl.isPrimaryClient, targetChange, - waitForRequeryResult + targetIsPendingReset ); updateTrackedLimbos( syncEngineImpl, diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index 8897d33abc9..7784b82021d 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -271,20 +271,21 @@ export class View { * Updates the view with the given ViewDocumentChanges and optionally updates * limbo docs and sync state from the provided target change. * @param docChanges - The set of changes to make to the view's docs. - * @param updateLimboDocuments - Whether to update limbo documents based on + * @param limboResolutionEnabled - Whether to update limbo documents based on * this change. * @param targetChange - A target change to apply for computing limbo docs and * sync state. - * @param waitForRequeryResult - Whether the target is pending to run a full - * re-query due to existence filter mismatch. + * @param targetIsPendingReset - Whether the target is pending to reset due to + * existence filter mismatch. If not explicitly specified, it is treated + * equivalently to false. * @returns A new ViewChange with the given docs, changes, and sync state. */ // PORTING NOTE: The iOS/Android clients always compute limbo document changes. applyChanges( docChanges: ViewDocumentChanges, - updateLimboDocuments: boolean, + limboResolutionEnabled: boolean, targetChange?: TargetChange, - waitForRequeryResult?: boolean + targetIsPendingReset?: boolean ): ViewChange { debugAssert( !docChanges.needsRefill, @@ -303,15 +304,17 @@ export class View { }); this.applyTargetChange(targetChange); - const limboChanges = updateLimboDocuments - ? this.updateLimboDocuments(waitForRequeryResult ?? false) - : []; + + targetIsPendingReset = targetIsPendingReset ?? false; + const limboChanges = + limboResolutionEnabled && !targetIsPendingReset + ? this.updateLimboDocuments() + : []; // We are at synced state if there is no limbo docs are waiting to be resolved, view is current - // with the backend, and the query is not pending for full re-query result due to existence - // filter mismatch. + // with the backend, and the query is not pending to reset due to existence filter mismatch. const synced = - this.limboDocuments.size === 0 && this.current && !waitForRequeryResult; + this.limboDocuments.size === 0 && this.current && !targetIsPendingReset; const newSyncState = synced ? SyncState.Synced : SyncState.Local; const syncStateChanged = newSyncState !== this.syncState; @@ -359,7 +362,7 @@ export class View { mutatedKeys: this.mutatedKeys, needsRefill: false }, - /* updateLimboDocuments= */ false + /* limboResolutionEnabled= */ false ); } else { // No effect, just return a no-op ViewChange. @@ -412,11 +415,9 @@ export class View { } } - private updateLimboDocuments( - waitForRequeryResult: boolean - ): LimboDocumentChange[] { + private updateLimboDocuments(): LimboDocumentChange[] { // We can only determine limbo documents when we're in-sync with the server. - if (waitForRequeryResult || !this.current) { + if (!this.current) { return []; } @@ -469,7 +470,7 @@ export class View { this._syncedDocuments = queryResult.remoteKeys; this.limboDocuments = documentKeySet(); const docChanges = this.computeDocChanges(queryResult.documents); - return this.applyChanges(docChanges, /*updateLimboDocuments=*/ true); + return this.applyChanges(docChanges, /* limboResolutionEnabled= */ true); } /** diff --git a/packages/firestore/test/unit/core/view.test.ts b/packages/firestore/test/unit/core/view.test.ts index b47cc0ea337..7e9f61bd6a3 100644 --- a/packages/firestore/test/unit/core/view.test.ts +++ b/packages/firestore/test/unit/core/view.test.ts @@ -304,19 +304,19 @@ describe('View', () => { let changes = view.computeDocChanges(documentUpdates(doc1)); let viewChange = view.applyChanges( changes, - /* updateLimboDocuments= */ true + /* limboResolutionEnabled= */ true ); expect(viewChange.snapshot!.fromCache).to.be.true; // Add doc2 to generate a snapshot. Doc1 is still missing. changes = view.computeDocChanges(documentUpdates(doc2)); - viewChange = view.applyChanges(changes, /* updateLimboDocuments= */ true); + viewChange = view.applyChanges(changes, /* limboResolutionEnabled= */ true); expect(viewChange.snapshot!.fromCache).to.be.true; // Add doc2 to the backend's result set. viewChange = view.applyChanges( changes, - /* updateLimboDocuments= */ true, + /* limboResolutionEnabled= */ true, updateMapping(version(0), [doc2], [], [], /* current= */ true) ); // We are CURRENT but doc1 is in limbo. @@ -325,7 +325,7 @@ describe('View', () => { // Add doc1 to the backend's result set. viewChange = view.applyChanges( changes, - /* updateLimboDocuments= */ true, + /* limboResolutionEnabled= */ true, updateMapping(version(0), [doc1], [], [], /* current= */ true) ); expect(viewChange.snapshot!.fromCache).to.be.false; diff --git a/packages/firestore/test/unit/local/query_engine.test.ts b/packages/firestore/test/unit/local/query_engine.test.ts index bf8ada916ef..d65626acf53 100644 --- a/packages/firestore/test/unit/local/query_engine.test.ts +++ b/packages/firestore/test/unit/local/query_engine.test.ts @@ -253,7 +253,7 @@ function genericQueryEngineTest( const viewDocChanges = view.computeDocChanges(docs); return view.applyChanges( viewDocChanges, - /*updateLimboDocuments=*/ true + /* limboResolutionEnabled= */ true ).snapshot!.docs; }); }); diff --git a/packages/firestore/test/unit/specs/limbo_spec.test.ts b/packages/firestore/test/unit/specs/limbo_spec.test.ts index d048167fbfc..0a4052cc72b 100644 --- a/packages/firestore/test/unit/specs/limbo_spec.test.ts +++ b/packages/firestore/test/unit/specs/limbo_spec.test.ts @@ -928,7 +928,7 @@ describeSpec('Limbo Documents:', [], () => { } ); - // Reproduce the bug in b/238823695 + // Regression test for the bug in https://github.com/firebase/firebase-android-sdk/issues/5357 specTest( 'Limbo resolution should wait for full re-query result if there is an existence filter mismatch ', [], @@ -949,8 +949,6 @@ describeSpec('Limbo Documents:', [], () => { .watchAcks(query1) // DocB is deleted in the next sync. .watchFilters([query1], [docA.key]) - // Bugged behavior: Missing watchCurrent here will move - // all the docs to limbo unnecessarily. .watchCurrents(query1, 'resume-token-2000') .watchSnapshots(2000) .expectActiveTargets({ @@ -962,7 +960,7 @@ describeSpec('Limbo Documents:', [], () => { .watchAcksFull(query1, 3000, docA) // Only the deleted doc is moved to limbo after re-query result. .expectLimboDocs(docB.key) - .ackLimbo(3000, deletedDoc('collection/b', 3000)) + .ackLimbo(3000, deletedDoc(docB.key.toString(), 3000)) .expectLimboDocs() .expectEvents(query1, { removed: [docB] From 5a917ee400e1301268081b84c3e28fed01a57a58 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Mon, 13 Nov 2023 12:04:49 -0500 Subject: [PATCH 8/9] format --- packages/firestore/src/core/view.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index 7784b82021d..b0a07bd783c 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -277,7 +277,7 @@ export class View { * sync state. * @param targetIsPendingReset - Whether the target is pending to reset due to * existence filter mismatch. If not explicitly specified, it is treated - * equivalently to false. + * equivalently to `false`. * @returns A new ViewChange with the given docs, changes, and sync state. */ // PORTING NOTE: The iOS/Android clients always compute limbo document changes. From 04aed322ad3ebda9fad52645e1483fdffc4b44c5 Mon Sep 17 00:00:00 2001 From: milaGGL <107142260+milaGGL@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:12:11 -0500 Subject: [PATCH 9/9] add changeset --- .changeset/olive-dogs-play.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/olive-dogs-play.md diff --git a/.changeset/olive-dogs-play.md b/.changeset/olive-dogs-play.md new file mode 100644 index 00000000000..406c6d86417 --- /dev/null +++ b/.changeset/olive-dogs-play.md @@ -0,0 +1,7 @@ +--- +'@firebase/firestore': patch +'firebase': patch +--- + +Fixed an issue in the local cache synchronization logic where all locally-cached documents that matched a resumed query would be unnecessarily re-downloaded; with the fix it now only downloads the documents that are known to be out-of-sync. +