21
21
import androidx .annotation .VisibleForTesting ;
22
22
import com .google .android .gms .tasks .Task ;
23
23
import com .google .android .gms .tasks .TaskCompletionSource ;
24
+ import com .google .common .collect .ImmutableMap ;
25
+ import com .google .common .collect .ImmutableSet ;
24
26
import com .google .firebase .database .collection .ImmutableSortedMap ;
25
27
import com .google .firebase .database .collection .ImmutableSortedSet ;
26
28
import com .google .firebase .firestore .FirebaseFirestoreException ;
59
61
import java .util .ArrayList ;
60
62
import java .util .Collections ;
61
63
import java .util .HashMap ;
64
+ import java .util .LinkedHashSet ;
62
65
import java .util .List ;
63
66
import java .util .Map ;
64
- import java .util .Queue ;
65
67
import java .util .Set ;
66
68
67
69
/**
@@ -130,7 +132,7 @@ interface SyncEngineCallback {
130
132
* The keys of documents that are in limbo for which we haven't yet started a limbo resolution
131
133
* query.
132
134
*/
133
- private final Queue <DocumentKey > enqueuedLimboResolutions ;
135
+ private final LinkedHashSet <DocumentKey > enqueuedLimboResolutions ;
134
136
135
137
/** Keeps track of the target ID for each document that is in limbo with an active target. */
136
138
private final Map <DocumentKey , Integer > activeLimboTargetsByKey ;
@@ -169,7 +171,7 @@ public SyncEngine(
169
171
queryViewsByQuery = new HashMap <>();
170
172
queriesByTarget = new HashMap <>();
171
173
172
- enqueuedLimboResolutions = new ArrayDeque <>();
174
+ enqueuedLimboResolutions = new LinkedHashSet <>();
173
175
activeLimboTargetsByKey = new HashMap <>();
174
176
activeLimboResolutionsByTarget = new HashMap <>();
175
177
limboDocumentRefs = new ReferenceSet ();
@@ -603,6 +605,7 @@ private void removeAndCleanupTarget(int targetId, Status status) {
603
605
}
604
606
605
607
private void removeLimboTarget (DocumentKey key ) {
608
+ enqueuedLimboResolutions .remove (key );
606
609
// It's possible that the target already got removed because the query failed. In that case,
607
610
// the key won't exist in `limboTargetsByKey`. Only do the cleanup if we still have the target.
608
611
Integer targetId = activeLimboTargetsByKey .get (key );
@@ -676,7 +679,7 @@ private void updateTrackedLimboDocuments(List<LimboDocumentChange> limboChanges,
676
679
677
680
private void trackLimboChange (LimboDocumentChange change ) {
678
681
DocumentKey key = change .getKey ();
679
- if (!activeLimboTargetsByKey .containsKey (key )) {
682
+ if (!activeLimboTargetsByKey .containsKey (key ) && ! enqueuedLimboResolutions . contains ( key ) ) {
680
683
Logger .debug (TAG , "New document in limbo: %s" , key );
681
684
enqueuedLimboResolutions .add (key );
682
685
pumpEnqueuedLimboResolutions ();
@@ -694,7 +697,8 @@ private void trackLimboChange(LimboDocumentChange change) {
694
697
private void pumpEnqueuedLimboResolutions () {
695
698
while (!enqueuedLimboResolutions .isEmpty ()
696
699
&& activeLimboTargetsByKey .size () < maxConcurrentLimboResolutions ) {
697
- DocumentKey key = enqueuedLimboResolutions .remove ();
700
+ DocumentKey key = enqueuedLimboResolutions .iterator ().next ();
701
+ enqueuedLimboResolutions .remove (key );
698
702
int limboTargetId = targetIdGenerator .nextId ();
699
703
activeLimboResolutionsByTarget .put (limboTargetId , new LimboResolution (key ));
700
704
activeLimboTargetsByKey .put (key , limboTargetId );
@@ -708,15 +712,15 @@ private void pumpEnqueuedLimboResolutions() {
708
712
}
709
713
710
714
@ VisibleForTesting
711
- public Map <DocumentKey , Integer > getActiveLimboDocumentResolutions () {
715
+ public ImmutableMap <DocumentKey , Integer > getActiveLimboDocumentResolutions () {
712
716
// Make a defensive copy as the Map continues to be modified.
713
- return new HashMap <> (activeLimboTargetsByKey );
717
+ return ImmutableMap . copyOf (activeLimboTargetsByKey );
714
718
}
715
719
716
720
@ 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 );
720
724
}
721
725
722
726
public void handleCredentialChange (User user ) {
0 commit comments