15
15
* limitations under the License.
16
16
*/
17
17
18
+ import { User } from '../auth/user' ;
19
+ import { ListenSequence } from '../core/listen_sequence' ;
18
20
import { SnapshotVersion } from '../core/snapshot_version' ;
21
+ import { documentKeySet } from '../model/collections' ;
19
22
import { DocumentKey } from '../model/document_key' ;
20
23
import { ResourcePath } from '../model/path' ;
21
24
import { debugAssert , fail , hardAssert } from '../util/assert' ;
@@ -25,10 +28,13 @@ import {
25
28
decodeResourcePath ,
26
29
encodeResourcePath
27
30
} from './encoded_resource_path' ;
31
+ import { IndexedDbDocumentOverlayCache } from './indexeddb_document_overlay_cache' ;
28
32
import {
29
33
dbDocumentSize ,
30
34
removeMutationBatch
31
35
} from './indexeddb_mutation_batch_impl' ;
36
+ import { IndexedDbMutationQueue } from './indexeddb_mutation_queue' ;
37
+ import { newIndexedDbRemoteDocumentCache } from './indexeddb_remote_document_cache' ;
32
38
import {
33
39
DbCollectionParent ,
34
40
DbDocumentMutation ,
@@ -107,16 +113,20 @@ import {
107
113
DbTargetQueryTargetsKeyPath ,
108
114
DbTargetStore
109
115
} from './indexeddb_sentinels' ;
116
+ import { IndexedDbTransaction } from './indexeddb_transaction' ;
117
+ import { LocalDocumentsView } from './local_documents_view' ;
110
118
import {
111
119
fromDbMutationBatch ,
112
120
fromDbTarget ,
113
121
LocalSerializer ,
114
122
toDbTarget
115
123
} from './local_serializer' ;
116
124
import { MemoryCollectionParentIndex } from './memory_index_manager' ;
125
+ import { MemoryEagerDelegate , MemoryPersistence } from './memory_persistence' ;
117
126
import { PersistencePromise } from './persistence_promise' ;
118
127
import { SimpleDbSchemaConverter , SimpleDbTransaction } from './simple_db' ;
119
128
129
+
120
130
/** Performs database creation and schema upgrades. */
121
131
export class SchemaConverter implements SimpleDbSchemaConverter {
122
132
constructor ( private readonly serializer : LocalSerializer ) { }
@@ -240,9 +250,9 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
240
250
}
241
251
242
252
if ( fromVersion < 14 && toVersion >= 14 ) {
243
- p = p . next ( ( ) => {
244
- createFieldIndex ( db ) ;
245
- } ) ;
253
+ p = p
254
+ . next ( ( ) => createFieldIndex ( db ) )
255
+ . next ( ( ) => this . runOverlayMigration ( db , simpleDbTransaction ) ) ;
246
256
}
247
257
248
258
return p ;
@@ -455,6 +465,95 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
455
465
} )
456
466
. next ( ( ) => PersistencePromise . waitFor ( writes ) ) ;
457
467
}
468
+
469
+ private runOverlayMigration (
470
+ db : IDBDatabase ,
471
+ transaction : SimpleDbTransaction
472
+ ) : PersistencePromise < void > {
473
+ const queuesStore = transaction . store < DbMutationQueueKey , DbMutationQueue > (
474
+ DbMutationQueueStore
475
+ ) ;
476
+ const mutationsStore = transaction . store <
477
+ DbMutationBatchKey ,
478
+ DbMutationBatch
479
+ > ( DbMutationBatchStore ) ;
480
+
481
+ const promises : Array < PersistencePromise < void > > = [ ] ;
482
+ let userIds = new Set < string > ( ) ;
483
+
484
+ return queuesStore
485
+ . loadAll ( )
486
+ . next ( queues => {
487
+ for ( const queue of queues ) {
488
+ userIds = userIds . add ( queue . userId ) ;
489
+ }
490
+ } )
491
+ . next ( ( ) => {
492
+ userIds . forEach ( userId => {
493
+ const user = new User ( userId ) ;
494
+ const remoteDocumentCache = newIndexedDbRemoteDocumentCache (
495
+ this . serializer
496
+ ) ;
497
+ const documentOverlayCache = IndexedDbDocumentOverlayCache . forUser (
498
+ this . serializer ,
499
+ user
500
+ ) ;
501
+ let allDocumentKeysForUser = documentKeySet ( ) ;
502
+ const range = IDBKeyRange . bound (
503
+ [ userId , BATCHID_UNKNOWN ] ,
504
+ [ userId , Number . POSITIVE_INFINITY ]
505
+ ) ;
506
+ promises . push (
507
+ mutationsStore
508
+ . loadAll ( DbMutationBatchUserMutationsIndex , range )
509
+ . next ( dbBatches => {
510
+ dbBatches . forEach ( dbBatch => {
511
+ hardAssert (
512
+ dbBatch . userId === userId ,
513
+ `Cannot process batch ${ dbBatch . batchId } from unexpected user`
514
+ ) ;
515
+ const batch = fromDbMutationBatch ( this . serializer , dbBatch ) ;
516
+ batch
517
+ . keys ( )
518
+ . forEach (
519
+ key =>
520
+ ( allDocumentKeysForUser =
521
+ allDocumentKeysForUser . add ( key ) )
522
+ ) ;
523
+ } ) ;
524
+ } )
525
+ . next ( ( ) => {
526
+ // NOTE: The index manager and the reference delegate are
527
+ // irrelevant for the purpose of recalculating and saving
528
+ // overlays. We can therefore simply use the memory
529
+ // implementation.
530
+ const memoryPersistence = new MemoryPersistence (
531
+ MemoryEagerDelegate . factory ,
532
+ this . serializer . remoteSerializer
533
+ ) ;
534
+ const indexManager = memoryPersistence . getIndexManager ( user ) ;
535
+ const mutationQueue = IndexedDbMutationQueue . forUser (
536
+ user ,
537
+ this . serializer ,
538
+ indexManager ,
539
+ memoryPersistence . referenceDelegate
540
+ ) ;
541
+ const localDocumentsView = new LocalDocumentsView (
542
+ remoteDocumentCache ,
543
+ mutationQueue ,
544
+ documentOverlayCache ,
545
+ indexManager
546
+ ) ;
547
+ return localDocumentsView . recalculateAndSaveOverlaysForDocumentKeys (
548
+ new IndexedDbTransaction ( transaction , ListenSequence . INVALID ) ,
549
+ allDocumentKeysForUser
550
+ ) ;
551
+ } )
552
+ ) ;
553
+ } ) ;
554
+ } )
555
+ . next ( ( ) => PersistencePromise . waitFor ( promises ) ) ;
556
+ }
458
557
}
459
558
460
559
function sentinelKey ( path : ResourcePath ) : DbTargetDocumentKey {
0 commit comments