Skip to content

Commit 95703c5

Browse files
Remove local references from reference delegate (#42)
1 parent b3871fe commit 95703c5

File tree

3 files changed

+46
-5
lines changed

3 files changed

+46
-5
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalStore.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,15 @@ public void releaseQuery(Query query) {
558558
queryCache.updateQueryData(queryData);
559559
}
560560

561-
localViewReferences.removeReferencesForId(queryData.getTargetId());
561+
// References for documents sent via Watch are automatically removed when we delete a
562+
// query's target data from the reference delegate. Since this does not remove references
563+
// for locally mutated documents, we have to remove the target associations for these
564+
// documents manually.
565+
ImmutableSortedSet<DocumentKey> removedReferences =
566+
localViewReferences.removeReferencesForId(queryData.getTargetId());
567+
for (DocumentKey key : removedReferences) {
568+
persistence.getReferenceDelegate().removeReference(key);
569+
}
562570
persistence.getReferenceDelegate().removeTarget(queryData);
563571
targetIds.remove(queryData.getTargetId());
564572

@@ -622,7 +630,7 @@ private Set<DocumentKey> releaseBatchResults(List<MutationBatchResult> batchResu
622630
ArrayList<MutationBatch> batches = new ArrayList<>(batchResults.size());
623631
// TODO: Call queryEngine.handleDocumentChange() as appropriate.
624632
for (MutationBatchResult batchResult : batchResults) {
625-
applyBatchResult(batchResult);
633+
applyWriteToRemoteDocuments(batchResult);
626634
batches.add(batchResult.getBatch());
627635
}
628636

@@ -647,7 +655,7 @@ private Set<DocumentKey> removeMutationBatches(List<MutationBatch> batches) {
647655
return affectedDocs;
648656
}
649657

650-
private void applyBatchResult(MutationBatchResult batchResult) {
658+
private void applyWriteToRemoteDocuments(MutationBatchResult batchResult) {
651659
MutationBatch batch = batchResult.getBatch();
652660
Set<DocumentKey> docKeys = batch.getKeys();
653661
for (DocumentKey docKey : docKeys) {

firebase-firestore/src/main/java/com/google/firebase/firestore/local/ReferenceSet.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,27 @@ public void removeReferences(ImmutableSortedSet<DocumentKey> keys, int targetOrB
7777
}
7878
}
7979

80-
/** Clears all references with a given ID. Calls removeReference() for each key removed. */
81-
public void removeReferencesForId(int targetId) {
80+
/**
81+
* Clears all references with a given ID. Calls removeReference() for each key removed.
82+
*
83+
* @return The keys of the documents that were removed.
84+
*/
85+
public ImmutableSortedSet<DocumentKey> removeReferencesForId(int targetId) {
8286
DocumentKey emptyKey = DocumentKey.empty();
8387
DocumentReference startRef = new DocumentReference(emptyKey, targetId);
8488
Iterator<DocumentReference> it = referencesByTarget.iteratorFrom(startRef);
89+
ImmutableSortedSet<DocumentKey> keys = DocumentKey.emptyKeySet();
8590
while (it.hasNext()) {
8691
DocumentReference ref = it.next();
8792
if (ref.getId() == targetId) {
93+
keys = keys.insert(ref.getKey());
8894
removeReference(ref);
8995
} else {
9096
break;
9197
}
9298
}
99+
100+
return keys;
93101
}
94102

95103
/** Clears all references for all IDs. */

firebase-firestore/src/test/java/com/google/firebase/firestore/local/LocalStoreTestCase.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,31 @@ public void testHandlesSetMutationThenDocument() {
239239
assertContains(doc("foo/bar", 2, map("foo", "bar"), true));
240240
}
241241

242+
@Test
243+
public void testHandlesSetMutationThenAckThenRelease() {
244+
Query query = Query.atPath(ResourcePath.fromSegments(asList("foo")));
245+
allocateQuery(query);
246+
247+
writeMutation(setMutation("foo/bar", map("foo", "bar")));
248+
assertChanged(doc("foo/bar", 0, map("foo", "bar"), true));
249+
assertContains(doc("foo/bar", 0, map("foo", "bar"), true));
250+
251+
acknowledgeMutation(1);
252+
notifyLocalViewChanges(viewChanges(2, asList("foo/bar"), emptyList()));
253+
254+
assertChanged();
255+
assertContains(doc("foo/bar", 0, map("foo", "bar"), true));
256+
257+
releaseQuery(query);
258+
259+
// It has been acknowledged, and should no longer be retained as there is no target and mutation
260+
if (garbageCollectorIsEager()) {
261+
assertNotContains("foo/bar");
262+
} else {
263+
assertContains(doc("foo/bar", 0, map("foo", "bar"), false));
264+
}
265+
}
266+
242267
@Test
243268
public void testHandlesAckThenRejectThenRemoteEvent() {
244269
// Start a query that requires acks to be held.

0 commit comments

Comments
 (0)