Skip to content

Commit c9fefbe

Browse files
authored
Dequeue limbo resolutions when their respective queries are stopped (#2404)
1 parent be59902 commit c9fefbe

File tree

3 files changed

+2246
-9
lines changed

3 files changed

+2246
-9
lines changed

firebase-firestore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
Bundles contain pre-packaged data produced with the NodeJS Server SDK and
55
can be used to populate Firestore's cache without reading documents from
66
the backend.
7+
- [fixed] Fixed a Firestore bug where local cache inconsistencies were
8+
unnecessarily being resolved, causing the `Task` objects returned from `get()`
9+
invocations to never complete (#2404).
710

811
# (22.0.2)
912
- [changed] A write to a document that contains FieldValue transforms is no

firebase-firestore/src/main/java/com/google/firebase/firestore/core/SyncEngine.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@
5555
import com.google.firebase.firestore.util.Util;
5656
import io.grpc.Status;
5757
import java.io.IOException;
58-
import java.util.ArrayDeque;
5958
import java.util.ArrayList;
6059
import java.util.Collections;
6160
import java.util.HashMap;
61+
import java.util.Iterator;
62+
import java.util.LinkedHashSet;
6263
import java.util.List;
6364
import java.util.Map;
64-
import java.util.Queue;
6565
import java.util.Set;
6666

6767
/**
@@ -130,7 +130,7 @@ interface SyncEngineCallback {
130130
* The keys of documents that are in limbo for which we haven't yet started a limbo resolution
131131
* query.
132132
*/
133-
private final Queue<DocumentKey> enqueuedLimboResolutions;
133+
private final LinkedHashSet<DocumentKey> enqueuedLimboResolutions;
134134

135135
/** Keeps track of the target ID for each document that is in limbo with an active target. */
136136
private final Map<DocumentKey, Integer> activeLimboTargetsByKey;
@@ -169,7 +169,7 @@ public SyncEngine(
169169
queryViewsByQuery = new HashMap<>();
170170
queriesByTarget = new HashMap<>();
171171

172-
enqueuedLimboResolutions = new ArrayDeque<>();
172+
enqueuedLimboResolutions = new LinkedHashSet<>();
173173
activeLimboTargetsByKey = new HashMap<>();
174174
activeLimboResolutionsByTarget = new HashMap<>();
175175
limboDocumentRefs = new ReferenceSet();
@@ -603,6 +603,7 @@ private void removeAndCleanupTarget(int targetId, Status status) {
603603
}
604604

605605
private void removeLimboTarget(DocumentKey key) {
606+
enqueuedLimboResolutions.remove(key);
606607
// It's possible that the target already got removed because the query failed. In that case,
607608
// the key won't exist in `limboTargetsByKey`. Only do the cleanup if we still have the target.
608609
Integer targetId = activeLimboTargetsByKey.get(key);
@@ -676,7 +677,7 @@ private void updateTrackedLimboDocuments(List<LimboDocumentChange> limboChanges,
676677

677678
private void trackLimboChange(LimboDocumentChange change) {
678679
DocumentKey key = change.getKey();
679-
if (!activeLimboTargetsByKey.containsKey(key)) {
680+
if (!activeLimboTargetsByKey.containsKey(key) && !enqueuedLimboResolutions.contains(key)) {
680681
Logger.debug(TAG, "New document in limbo: %s", key);
681682
enqueuedLimboResolutions.add(key);
682683
pumpEnqueuedLimboResolutions();
@@ -694,7 +695,9 @@ private void trackLimboChange(LimboDocumentChange change) {
694695
private void pumpEnqueuedLimboResolutions() {
695696
while (!enqueuedLimboResolutions.isEmpty()
696697
&& activeLimboTargetsByKey.size() < maxConcurrentLimboResolutions) {
697-
DocumentKey key = enqueuedLimboResolutions.remove();
698+
Iterator<DocumentKey> it = enqueuedLimboResolutions.iterator();
699+
DocumentKey key = it.next();
700+
it.remove();
698701
int limboTargetId = targetIdGenerator.nextId();
699702
activeLimboResolutionsByTarget.put(limboTargetId, new LimboResolution(key));
700703
activeLimboTargetsByKey.put(key, limboTargetId);
@@ -714,9 +717,9 @@ public Map<DocumentKey, Integer> getActiveLimboDocumentResolutions() {
714717
}
715718

716719
@VisibleForTesting
717-
public Queue<DocumentKey> getEnqueuedLimboDocumentResolutions() {
718-
// Make a defensive copy as the Queue continues to be modified.
719-
return new ArrayDeque<>(enqueuedLimboResolutions);
720+
public List<DocumentKey> getEnqueuedLimboDocumentResolutions() {
721+
// Make a defensive copy as the LinkedHashSet continues to be modified.
722+
return new ArrayList<>(enqueuedLimboResolutions);
720723
}
721724

722725
public void handleCredentialChange(User user) {

0 commit comments

Comments
 (0)