Skip to content

Commit 20da793

Browse files
committed
Remove enqueued limbo resolutions when a query stops and avoid starting one if already enqueued.
1 parent 6ce7880 commit 20da793

File tree

2 files changed

+2245
-10
lines changed

2 files changed

+2245
-10
lines changed

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import androidx.annotation.VisibleForTesting;
2222
import com.google.android.gms.tasks.Task;
2323
import com.google.android.gms.tasks.TaskCompletionSource;
24+
import com.google.common.collect.ImmutableMap;
25+
import com.google.common.collect.ImmutableSet;
2426
import com.google.firebase.database.collection.ImmutableSortedMap;
2527
import com.google.firebase.database.collection.ImmutableSortedSet;
2628
import com.google.firebase.firestore.FirebaseFirestoreException;
@@ -59,9 +61,9 @@
5961
import java.util.ArrayList;
6062
import java.util.Collections;
6163
import java.util.HashMap;
64+
import java.util.LinkedHashSet;
6265
import java.util.List;
6366
import java.util.Map;
64-
import java.util.Queue;
6567
import java.util.Set;
6668

6769
/**
@@ -130,7 +132,7 @@ interface SyncEngineCallback {
130132
* The keys of documents that are in limbo for which we haven't yet started a limbo resolution
131133
* query.
132134
*/
133-
private final Queue<DocumentKey> enqueuedLimboResolutions;
135+
private final LinkedHashSet<DocumentKey> enqueuedLimboResolutions;
134136

135137
/** Keeps track of the target ID for each document that is in limbo with an active target. */
136138
private final Map<DocumentKey, Integer> activeLimboTargetsByKey;
@@ -169,7 +171,7 @@ public SyncEngine(
169171
queryViewsByQuery = new HashMap<>();
170172
queriesByTarget = new HashMap<>();
171173

172-
enqueuedLimboResolutions = new ArrayDeque<>();
174+
enqueuedLimboResolutions = new LinkedHashSet<>();
173175
activeLimboTargetsByKey = new HashMap<>();
174176
activeLimboResolutionsByTarget = new HashMap<>();
175177
limboDocumentRefs = new ReferenceSet();
@@ -603,6 +605,7 @@ private void removeAndCleanupTarget(int targetId, Status status) {
603605
}
604606

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

677680
private void trackLimboChange(LimboDocumentChange change) {
678681
DocumentKey key = change.getKey();
679-
if (!activeLimboTargetsByKey.containsKey(key)) {
682+
if (!activeLimboTargetsByKey.containsKey(key) && !enqueuedLimboResolutions.contains(key)) {
680683
Logger.debug(TAG, "New document in limbo: %s", key);
681684
enqueuedLimboResolutions.add(key);
682685
pumpEnqueuedLimboResolutions();
@@ -694,7 +697,8 @@ private void trackLimboChange(LimboDocumentChange change) {
694697
private void pumpEnqueuedLimboResolutions() {
695698
while (!enqueuedLimboResolutions.isEmpty()
696699
&& activeLimboTargetsByKey.size() < maxConcurrentLimboResolutions) {
697-
DocumentKey key = enqueuedLimboResolutions.remove();
700+
DocumentKey key = enqueuedLimboResolutions.iterator().next();
701+
enqueuedLimboResolutions.remove(key);
698702
int limboTargetId = targetIdGenerator.nextId();
699703
activeLimboResolutionsByTarget.put(limboTargetId, new LimboResolution(key));
700704
activeLimboTargetsByKey.put(key, limboTargetId);
@@ -708,15 +712,15 @@ private void pumpEnqueuedLimboResolutions() {
708712
}
709713

710714
@VisibleForTesting
711-
public Map<DocumentKey, Integer> getActiveLimboDocumentResolutions() {
715+
public ImmutableMap<DocumentKey, Integer> getActiveLimboDocumentResolutions() {
712716
// Make a defensive copy as the Map continues to be modified.
713-
return new HashMap<>(activeLimboTargetsByKey);
717+
return ImmutableMap.copyOf(activeLimboTargetsByKey);
714718
}
715719

716720
@VisibleForTesting
717-
public Queue<DocumentKey> getEnqueuedLimboDocumentResolutions() {
718-
// Make a defensive copy as the Queue continues to be modified.
719-
return new ArrayDeque<>(enqueuedLimboResolutions);
721+
public ImmutableSet<DocumentKey> getEnqueuedLimboDocumentResolutions() {
722+
// Make a defensive copy as the LinkedHashMap continues to be modified.
723+
return ImmutableSet.copyOf(enqueuedLimboResolutions);
720724
}
721725

722726
public void handleCredentialChange(User user) {

0 commit comments

Comments
 (0)