@@ -19,6 +19,7 @@ import { Query } from '../core/query';
19
19
import { SnapshotVersion } from '../core/snapshot_version' ;
20
20
import {
21
21
DocumentKeySet ,
22
+ documentKeySet ,
22
23
DocumentMap ,
23
24
documentMap ,
24
25
MaybeDocumentMap ,
@@ -34,6 +35,7 @@ import { ResourcePath } from '../model/path';
34
35
import { assert } from '../util/assert' ;
35
36
import { IndexManager } from './index_manager' ;
36
37
import { MutationQueue } from './mutation_queue' ;
38
+ import { PatchMutation } from '../model/mutation' ;
37
39
import { PersistenceTransaction } from './persistence' ;
38
40
import { PersistencePromise } from './persistence_promise' ;
39
41
import { RemoteDocumentCache } from './remote_document_cache' ;
@@ -49,7 +51,7 @@ export class LocalDocumentsView {
49
51
private remoteDocumentCache : RemoteDocumentCache ,
50
52
private mutationQueue : MutationQueue ,
51
53
private indexManager : IndexManager
52
- ) { }
54
+ ) { }
53
55
54
56
/**
55
57
* Get the local view of the document identified by `key`.
@@ -208,6 +210,7 @@ export class LocalDocumentsView {
208
210
) : PersistencePromise < DocumentMap > {
209
211
// Query the remote documents and overlay mutations.
210
212
let results : DocumentMap ;
213
+ let mutationBatches : MutationBatch [ ] ;
211
214
return this . remoteDocumentCache
212
215
. getDocumentsMatchingQuery ( transaction , query )
213
216
. next ( queryResults => {
@@ -218,27 +221,41 @@ export class LocalDocumentsView {
218
221
) ;
219
222
} )
220
223
. next ( matchingMutationBatches => {
221
- for ( const batch of matchingMutationBatches ) {
222
- for ( const mutation of batch . mutations ) {
223
- const key = mutation . key ;
224
- // Only process documents belonging to the collection.
225
- if ( ! query . path . isImmediateParentOf ( key . path ) ) {
226
- continue ;
224
+ mutationBatches = matchingMutationBatches ;
225
+ // It is possible that a PatchMutation can make a document match a query, even if
226
+ // the version in the RemoteDocumentCache is not a match yet (waiting for server
227
+ // to ack). To handle this, we find all document keys affected by the PatchMutations
228
+ // that are not in `result` yet, and back fill them via `remoteDocumentCache.getEntries`,
229
+ // otherwise those `PatchMutations` will be ignored because no base document can be found,
230
+ // and lead to missing result for the query.
231
+ return this . getMissingBaseDocuments (
232
+ transaction ,
233
+ mutationBatches ,
234
+ results
235
+ ) . next ( missingBaseDocuments => {
236
+ missingBaseDocuments . forEach ( ( key , doc ) => {
237
+ if ( doc !== null && doc instanceof Document ) {
238
+ results = results . insert ( key , doc ) ;
227
239
}
240
+ } ) ;
228
241
229
- const baseDoc = results . get ( key ) ;
230
- const mutatedDoc = mutation . applyToLocalView (
231
- baseDoc ,
232
- baseDoc ,
233
- batch . localWriteTime
234
- ) ;
235
- if ( mutatedDoc instanceof Document ) {
236
- results = results . insert ( key , mutatedDoc ) ;
237
- } else {
238
- results = results . remove ( key ) ;
242
+ for ( const batch of mutationBatches ) {
243
+ for ( const mutation of batch . mutations ) {
244
+ const key = mutation . key ;
245
+ const baseDoc = results . get ( key ) ;
246
+ const mutatedDoc = mutation . applyToLocalView (
247
+ baseDoc ,
248
+ baseDoc ,
249
+ batch . localWriteTime
250
+ ) ;
251
+ if ( mutatedDoc instanceof Document ) {
252
+ results = results . insert ( key , mutatedDoc ) ;
253
+ } else {
254
+ results = results . remove ( key ) ;
255
+ }
239
256
}
240
257
}
241
- }
258
+ } ) ;
242
259
} )
243
260
. next ( ( ) => {
244
261
// Finally, filter out any documents that don't actually match
@@ -252,4 +269,28 @@ export class LocalDocumentsView {
252
269
return results ;
253
270
} ) ;
254
271
}
272
+
273
+ private getMissingBaseDocuments (
274
+ transaction : PersistenceTransaction ,
275
+ matchingMutationBatches : MutationBatch [ ] ,
276
+ existingDocuments : DocumentMap
277
+ ) : PersistencePromise < NullableMaybeDocumentMap > {
278
+ let missingBaseDocEntriesForPatching = documentKeySet ( ) ;
279
+ for ( const batch of matchingMutationBatches ) {
280
+ for ( const mutation of batch . mutations ) {
281
+ if (
282
+ mutation instanceof PatchMutation &&
283
+ existingDocuments . get ( mutation . key ) === null
284
+ ) {
285
+ missingBaseDocEntriesForPatching = missingBaseDocEntriesForPatching . add (
286
+ mutation . key
287
+ ) ;
288
+ }
289
+ }
290
+ }
291
+ return this . remoteDocumentCache . getEntries (
292
+ transaction ,
293
+ missingBaseDocEntriesForPatching
294
+ ) ;
295
+ }
255
296
}
0 commit comments