|
28 | 28 | import com.google.firebase.firestore.model.SnapshotVersion;
|
29 | 29 | import com.google.firebase.firestore.model.mutation.Mutation;
|
30 | 30 | import com.google.firebase.firestore.model.mutation.MutationBatch;
|
| 31 | +import com.google.firebase.firestore.model.mutation.PatchMutation; |
| 32 | +import java.util.HashSet; |
31 | 33 | import java.util.List;
|
32 | 34 | import java.util.Map;
|
33 | 35 | import javax.annotation.Nullable;
|
@@ -182,6 +184,9 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollection
|
182 | 184 | remoteDocumentCache.getAllDocumentsMatchingQuery(query);
|
183 | 185 |
|
184 | 186 | List<MutationBatch> matchingBatches = mutationQueue.getAllMutationBatchesAffectingQuery(query);
|
| 187 | + |
| 188 | + results = addMissingBaseDocuments(matchingBatches, results); |
| 189 | + |
185 | 190 | for (MutationBatch batch : matchingBatches) {
|
186 | 191 | for (Mutation mutation : batch.getMutations()) {
|
187 | 192 | // Only process documents belonging to the collection.
|
@@ -210,4 +215,34 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollection
|
210 | 215 |
|
211 | 216 | return results;
|
212 | 217 | }
|
| 218 | + |
| 219 | + /** |
| 220 | + * It is possible that a {@code PatchMutation} can make a document match a query, even if the |
| 221 | + * version in the {@code RemoteDocumentCache} is not a match yet (waiting for server to ack). To |
| 222 | + * handle this, we find all document keys affected by the {@code PatchMutation}s that are not in |
| 223 | + * {@code existingDocs} yet, and back fill them via {@code remoteDocumentCache.getAll}, otherwise |
| 224 | + * those {@code PatchMutation}s will be ignored because no base document can be found, and lead to |
| 225 | + * missing results for the query. |
| 226 | + */ |
| 227 | + private ImmutableSortedMap<DocumentKey, Document> addMissingBaseDocuments( |
| 228 | + List<MutationBatch> matchingBatches, ImmutableSortedMap<DocumentKey, Document> existingDocs) { |
| 229 | + HashSet<DocumentKey> missingDocKeys = new HashSet<>(); |
| 230 | + for (MutationBatch batch : matchingBatches) { |
| 231 | + for (Mutation mutation : batch.getMutations()) { |
| 232 | + if (mutation instanceof PatchMutation && !existingDocs.containsKey(mutation.getKey())) { |
| 233 | + missingDocKeys.add(mutation.getKey()); |
| 234 | + } |
| 235 | + } |
| 236 | + } |
| 237 | + |
| 238 | + ImmutableSortedMap<DocumentKey, Document> mergedDocs = existingDocs; |
| 239 | + Map<DocumentKey, MaybeDocument> missingDocs = remoteDocumentCache.getAll(missingDocKeys); |
| 240 | + for (Map.Entry<DocumentKey, MaybeDocument> entry : missingDocs.entrySet()) { |
| 241 | + if (entry.getValue() != null && (entry.getValue() instanceof Document)) { |
| 242 | + mergedDocs = mergedDocs.insert(entry.getKey(), (Document) entry.getValue()); |
| 243 | + } |
| 244 | + } |
| 245 | + |
| 246 | + return mergedDocs; |
| 247 | + } |
213 | 248 | }
|
0 commit comments