@@ -42,10 +42,11 @@ import { Query } from './query';
42
42
import { Transaction } from './transaction' ;
43
43
import { ViewSnapshot } from './view_snapshot' ;
44
44
import {
45
- OnlineComponentProvider ,
46
45
MemoryOfflineComponentProvider ,
47
- OfflineComponentProvider
46
+ OfflineComponentProvider ,
47
+ OnlineComponentProvider
48
48
} from './component_provider' ;
49
+ import { PartialObserver , Unsubscribe } from '../api/observer' ;
49
50
import { AsyncObserver } from '../util/async_observer' ;
50
51
51
52
const LOG_TAG = 'FirestoreClient' ;
@@ -92,6 +93,15 @@ export class FirestoreClient {
92
93
93
94
private readonly clientId = AutoId . newId ( ) ;
94
95
96
+ // We defer our initialization until we get the current user from
97
+ // setChangeListener(). We block the async queue until we got the initial
98
+ // user and the initialization is completed. This will prevent any scheduled
99
+ // work from happening before initialization is completed.
100
+ //
101
+ // If initializationDone resolved then the FirestoreClient is in a usable
102
+ // state.
103
+ private readonly initializationDone = new Deferred < void > ( ) ;
104
+
95
105
constructor (
96
106
private credentials : CredentialsProvider ,
97
107
/**
@@ -155,15 +165,6 @@ export class FirestoreClient {
155
165
156
166
this . databaseInfo = databaseInfo ;
157
167
158
- // We defer our initialization until we get the current user from
159
- // setChangeListener(). We block the async queue until we got the initial
160
- // user and the initialization is completed. This will prevent any scheduled
161
- // work from happening before initialization is completed.
162
- //
163
- // If initializationDone resolved then the FirestoreClient is in a usable
164
- // state.
165
- const initializationDone = new Deferred < void > ( ) ;
166
-
167
168
// If usePersistence is true, certain classes of errors while starting are
168
169
// recoverable but only by falling back to persistence disabled.
169
170
//
@@ -185,7 +186,7 @@ export class FirestoreClient {
185
186
persistenceSettings ,
186
187
user ,
187
188
persistenceResult
188
- ) . then ( initializationDone . resolve , initializationDone . reject ) ;
189
+ ) . then ( this . initializationDone . resolve , this . initializationDone . reject ) ;
189
190
} else {
190
191
this . asyncQueue . enqueueRetryable ( ( ) =>
191
192
this . remoteStore . handleCredentialChange ( user )
@@ -194,9 +195,7 @@ export class FirestoreClient {
194
195
} ) ;
195
196
196
197
// Block the async queue until initialization is done
197
- this . asyncQueue . enqueueAndForget ( ( ) => {
198
- return initializationDone . promise ;
199
- } ) ;
198
+ this . asyncQueue . enqueueAndForget ( ( ) => this . initializationDone . promise ) ;
200
199
201
200
// Return only the result of enabling persistence. Note that this does not
202
201
// need to await the completion of initializationDone because the result of
@@ -408,62 +407,22 @@ export class FirestoreClient {
408
407
docKey : DocumentKey
409
408
) : Promise < Document | null > {
410
409
this . verifyNotTerminated ( ) ;
411
- const deferred = new Deferred < Document | null > ( ) ;
412
- await this . asyncQueue . enqueue ( async ( ) => {
413
- try {
414
- const maybeDoc = await this . localStore . readDocument ( docKey ) ;
415
- if ( maybeDoc instanceof Document ) {
416
- deferred . resolve ( maybeDoc ) ;
417
- } else if ( maybeDoc instanceof NoDocument ) {
418
- deferred . resolve ( null ) ;
419
- } else {
420
- deferred . reject (
421
- new FirestoreError (
422
- Code . UNAVAILABLE ,
423
- 'Failed to get document from cache. (However, this document may ' +
424
- "exist on the server. Run again without setting 'source' in " +
425
- 'the GetOptions to attempt to retrieve the document from the ' +
426
- 'server.)'
427
- )
428
- ) ;
429
- }
430
- } catch ( e ) {
431
- const firestoreError = wrapInUserErrorIfRecoverable (
432
- e ,
433
- `Failed to get document '${ docKey } from cache`
434
- ) ;
435
- deferred . reject ( firestoreError ) ;
436
- }
437
- } ) ;
438
-
439
- return deferred . promise ;
410
+ await this . initializationDone . promise ;
411
+ return enqueueReadDocumentFromCache (
412
+ this . asyncQueue ,
413
+ this . localStore ,
414
+ docKey
415
+ ) ;
440
416
}
441
417
442
418
async getDocumentsFromLocalCache ( query : Query ) : Promise < ViewSnapshot > {
443
419
this . verifyNotTerminated ( ) ;
444
- const deferred = new Deferred < ViewSnapshot > ( ) ;
445
- await this . asyncQueue . enqueue ( async ( ) => {
446
- try {
447
- const queryResult = await this . localStore . executeQuery (
448
- query ,
449
- /* usePreviousResults= */ true
450
- ) ;
451
- const view = new View ( query , queryResult . remoteKeys ) ;
452
- const viewDocChanges = view . computeDocChanges ( queryResult . documents ) ;
453
- const viewChange = view . applyChanges (
454
- viewDocChanges ,
455
- /* updateLimboDocuments= */ false
456
- ) ;
457
- deferred . resolve ( viewChange . snapshot ! ) ;
458
- } catch ( e ) {
459
- const firestoreError = wrapInUserErrorIfRecoverable (
460
- e ,
461
- `Failed to execute query '${ query } against cache`
462
- ) ;
463
- deferred . reject ( firestoreError ) ;
464
- }
465
- } ) ;
466
- return deferred . promise ;
420
+ await this . initializationDone . promise ;
421
+ return enqueueExecuteQueryFromCache (
422
+ this . asyncQueue ,
423
+ this . localStore ,
424
+ query
425
+ ) ;
467
426
}
468
427
469
428
write ( mutations : Mutation [ ] ) : Promise < void > {
@@ -512,3 +471,134 @@ export class FirestoreClient {
512
471
return deferred . promise ;
513
472
}
514
473
}
474
+
475
+ export function enqueueWrite (
476
+ asyncQueue : AsyncQueue ,
477
+ syncEngine : SyncEngine ,
478
+ mutations : Mutation [ ]
479
+ ) : Promise < void > {
480
+ const deferred = new Deferred < void > ( ) ;
481
+ asyncQueue . enqueueAndForget ( ( ) => syncEngine . write ( mutations , deferred ) ) ;
482
+ return deferred . promise ;
483
+ }
484
+
485
+ export function enqueueNetworkEnabled (
486
+ asyncQueue : AsyncQueue ,
487
+ remoteStore : RemoteStore ,
488
+ persistence : Persistence ,
489
+ enabled : boolean
490
+ ) : Promise < void > {
491
+ return asyncQueue . enqueue ( ( ) => {
492
+ persistence . setNetworkEnabled ( enabled ) ;
493
+ return enabled ? remoteStore . enableNetwork ( ) : remoteStore . disableNetwork ( ) ;
494
+ } ) ;
495
+ }
496
+
497
+ export function enqueueWaitForPendingWrites (
498
+ asyncQueue : AsyncQueue ,
499
+ syncEngine : SyncEngine
500
+ ) : Promise < void > {
501
+ const deferred = new Deferred < void > ( ) ;
502
+ asyncQueue . enqueueAndForget ( ( ) => {
503
+ return syncEngine . registerPendingWritesCallback ( deferred ) ;
504
+ } ) ;
505
+ return deferred . promise ;
506
+ }
507
+
508
+ export function enqueueListen (
509
+ asyncQueue : AsyncQueue ,
510
+ eventManger : EventManager ,
511
+ query : Query ,
512
+ options : ListenOptions ,
513
+ observer : PartialObserver < ViewSnapshot >
514
+ ) : Unsubscribe {
515
+ const wrappedObserver = new AsyncObserver ( observer ) ;
516
+ const listener = new QueryListener ( query , wrappedObserver , options ) ;
517
+ asyncQueue . enqueueAndForget ( ( ) => eventManger . listen ( listener ) ) ;
518
+ return ( ) => {
519
+ wrappedObserver . mute ( ) ;
520
+ asyncQueue . enqueueAndForget ( ( ) => eventManger . unlisten ( listener ) ) ;
521
+ } ;
522
+ }
523
+
524
+ export function enqueueSnapshotsInSyncListen (
525
+ asyncQueue : AsyncQueue ,
526
+ eventManager : EventManager ,
527
+ observer : PartialObserver < void >
528
+ ) : Unsubscribe {
529
+ const wrappedObserver = new AsyncObserver ( observer ) ;
530
+ asyncQueue . enqueueAndForget ( async ( ) =>
531
+ eventManager . addSnapshotsInSyncListener ( wrappedObserver )
532
+ ) ;
533
+ return ( ) => {
534
+ wrappedObserver . mute ( ) ;
535
+ asyncQueue . enqueueAndForget ( async ( ) =>
536
+ eventManager . removeSnapshotsInSyncListener ( wrappedObserver )
537
+ ) ;
538
+ } ;
539
+ }
540
+
541
+ export async function enqueueReadDocumentFromCache (
542
+ asyncQueue : AsyncQueue ,
543
+ localStore : LocalStore ,
544
+ docKey : DocumentKey
545
+ ) : Promise < Document | null > {
546
+ const deferred = new Deferred < Document | null > ( ) ;
547
+ await asyncQueue . enqueue ( async ( ) => {
548
+ try {
549
+ const maybeDoc = await localStore . readDocument ( docKey ) ;
550
+ if ( maybeDoc instanceof Document ) {
551
+ deferred . resolve ( maybeDoc ) ;
552
+ } else if ( maybeDoc instanceof NoDocument ) {
553
+ deferred . resolve ( null ) ;
554
+ } else {
555
+ deferred . reject (
556
+ new FirestoreError (
557
+ Code . UNAVAILABLE ,
558
+ 'Failed to get document from cache. (However, this document may ' +
559
+ "exist on the server. Run again without setting 'source' in " +
560
+ 'the GetOptions to attempt to retrieve the document from the ' +
561
+ 'server.)'
562
+ )
563
+ ) ;
564
+ }
565
+ } catch ( e ) {
566
+ const firestoreError = wrapInUserErrorIfRecoverable (
567
+ e ,
568
+ `Failed to get document '${ docKey } from cache`
569
+ ) ;
570
+ deferred . reject ( firestoreError ) ;
571
+ }
572
+ } ) ;
573
+ return deferred . promise ;
574
+ }
575
+
576
+ export async function enqueueExecuteQueryFromCache (
577
+ asyncQueue : AsyncQueue ,
578
+ localStore : LocalStore ,
579
+ query : Query
580
+ ) : Promise < ViewSnapshot > {
581
+ const deferred = new Deferred < ViewSnapshot > ( ) ;
582
+ await asyncQueue . enqueue ( async ( ) => {
583
+ try {
584
+ const queryResult = await localStore . executeQuery (
585
+ query ,
586
+ /* usePreviousResults= */ true
587
+ ) ;
588
+ const view = new View ( query , queryResult . remoteKeys ) ;
589
+ const viewDocChanges = view . computeDocChanges ( queryResult . documents ) ;
590
+ const viewChange = view . applyChanges (
591
+ viewDocChanges ,
592
+ /* updateLimboDocuments= */ false
593
+ ) ;
594
+ deferred . resolve ( viewChange . snapshot ! ) ;
595
+ } catch ( e ) {
596
+ const firestoreError = wrapInUserErrorIfRecoverable (
597
+ e ,
598
+ `Failed to execute query '${ query } against cache`
599
+ ) ;
600
+ deferred . reject ( firestoreError ) ;
601
+ }
602
+ } ) ;
603
+ return deferred . promise ;
604
+ }
0 commit comments