@@ -24,7 +24,8 @@ import {
24
24
MaybeDocumentMap ,
25
25
maybeDocumentMap ,
26
26
NullableMaybeDocumentMap ,
27
- nullableMaybeDocumentMap
27
+ nullableMaybeDocumentMap ,
28
+ documentKeySet ,
28
29
} from '../model/collections' ;
29
30
import { Document , MaybeDocument , NoDocument } from '../model/document' ;
30
31
import { DocumentKey } from '../model/document_key' ;
@@ -37,6 +38,7 @@ import { MutationQueue } from './mutation_queue';
37
38
import { PersistenceTransaction } from './persistence' ;
38
39
import { PersistencePromise } from './persistence_promise' ;
39
40
import { RemoteDocumentCache } from './remote_document_cache' ;
41
+ import { PatchMutation } from '../model/mutation' ;
40
42
41
43
/**
42
44
* A readonly view of the local state of all documents we're tracking (i.e. we
@@ -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,7 +221,35 @@ export class LocalDocumentsView {
218
221
) ;
219
222
} )
220
223
. next ( matchingMutationBatches => {
224
+ mutationBatches = matchingMutationBatches ;
225
+ // It is possible that a PatchMutation can make a document a match to the query,
226
+ // but the version in `remoteDocumentCache` is not a match yet (waiting for server
227
+ // to ack). To handle this, we find all document keys affected by some`PatchMutation`s
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
+ let missingBaseDocEntriesForPatching = documentKeySet ( ) ;
221
232
for ( const batch of matchingMutationBatches ) {
233
+ for ( const mutation of batch . mutations ) {
234
+ const key = mutation . key ;
235
+ // Only process documents belonging to the collection.
236
+ if ( ! query . path . isImmediateParentOf ( key . path ) ) {
237
+ continue ;
238
+ }
239
+ if ( mutation instanceof PatchMutation && results . get ( mutation . key ) === null ) {
240
+ missingBaseDocEntriesForPatching = missingBaseDocEntriesForPatching . add ( mutation . key ) ;
241
+ }
242
+ }
243
+ }
244
+ return this . remoteDocumentCache . getEntries ( transaction , missingBaseDocEntriesForPatching ) ;
245
+ } )
246
+ . next ( baseDocsForPatching => {
247
+ baseDocsForPatching . forEach ( ( key , doc ) => {
248
+ if ( doc !== null && doc instanceof Document ) {
249
+ results = results . insert ( key , doc ) ;
250
+ }
251
+ } ) ;
252
+ for ( const batch of mutationBatches ) {
222
253
for ( const mutation of batch . mutations ) {
223
254
const key = mutation . key ;
224
255
// Only process documents belonging to the collection.
0 commit comments