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,13 +113,16 @@ 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
@@ -240,9 +249,9 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
240
249
}
241
250
242
251
if ( fromVersion < 14 && toVersion >= 14 ) {
243
- p = p . next ( ( ) => {
244
- createFieldIndex ( db ) ;
245
- } ) ;
252
+ p = p
253
+ . next ( ( ) => createFieldIndex ( db ) )
254
+ . next ( ( ) => this . runOverlayMigration ( db , simpleDbTransaction ) ) ;
246
255
}
247
256
248
257
return p ;
@@ -455,6 +464,95 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
455
464
} )
456
465
. next ( ( ) => PersistencePromise . waitFor ( writes ) ) ;
457
466
}
467
+
468
+ private runOverlayMigration (
469
+ db : IDBDatabase ,
470
+ transaction : SimpleDbTransaction
471
+ ) : PersistencePromise < void > {
472
+ const queuesStore = transaction . store < DbMutationQueueKey , DbMutationQueue > (
473
+ DbMutationQueueStore
474
+ ) ;
475
+ const mutationsStore = transaction . store <
476
+ DbMutationBatchKey ,
477
+ DbMutationBatch
478
+ > ( DbMutationBatchStore ) ;
479
+
480
+ const promises : Array < PersistencePromise < void > > = [ ] ;
481
+ let userIds = new Set < string > ( ) ;
482
+
483
+ return queuesStore
484
+ . loadAll ( )
485
+ . next ( queues => {
486
+ for ( const queue of queues ) {
487
+ userIds = userIds . add ( queue . userId ) ;
488
+ }
489
+ } )
490
+ . next ( ( ) => {
491
+ userIds . forEach ( userId => {
492
+ const user = new User ( userId ) ;
493
+ const remoteDocumentCache = newIndexedDbRemoteDocumentCache (
494
+ this . serializer
495
+ ) ;
496
+ const documentOverlayCache = IndexedDbDocumentOverlayCache . forUser (
497
+ this . serializer ,
498
+ user
499
+ ) ;
500
+ let allDocumentKeysForUser = documentKeySet ( ) ;
501
+ const range = IDBKeyRange . bound (
502
+ [ userId , BATCHID_UNKNOWN ] ,
503
+ [ userId , Number . POSITIVE_INFINITY ]
504
+ ) ;
505
+ promises . push (
506
+ mutationsStore
507
+ . loadAll ( DbMutationBatchUserMutationsIndex , range )
508
+ . next ( dbBatches => {
509
+ dbBatches . forEach ( dbBatch => {
510
+ hardAssert (
511
+ dbBatch . userId === userId ,
512
+ `Cannot process batch ${ dbBatch . batchId } from unexpected user`
513
+ ) ;
514
+ const batch = fromDbMutationBatch ( this . serializer , dbBatch ) ;
515
+ batch
516
+ . keys ( )
517
+ . forEach (
518
+ key =>
519
+ ( allDocumentKeysForUser =
520
+ allDocumentKeysForUser . add ( key ) )
521
+ ) ;
522
+ } ) ;
523
+ } )
524
+ . next ( ( ) => {
525
+ // NOTE: The index manager and the reference delegate are
526
+ // irrelevant for the purpose of recalculating and saving
527
+ // overlays. We can therefore simply use the memory
528
+ // implementation.
529
+ const memoryPersistence = new MemoryPersistence (
530
+ MemoryEagerDelegate . factory ,
531
+ this . serializer . remoteSerializer
532
+ ) ;
533
+ const indexManager = memoryPersistence . getIndexManager ( user ) ;
534
+ const mutationQueue = IndexedDbMutationQueue . forUser (
535
+ user ,
536
+ this . serializer ,
537
+ indexManager ,
538
+ memoryPersistence . referenceDelegate
539
+ ) ;
540
+ const localDocumentsView = new LocalDocumentsView (
541
+ remoteDocumentCache ,
542
+ mutationQueue ,
543
+ documentOverlayCache ,
544
+ indexManager
545
+ ) ;
546
+ return localDocumentsView . recalculateAndSaveOverlaysForDocumentKeys (
547
+ new IndexedDbTransaction ( transaction , ListenSequence . INVALID ) ,
548
+ allDocumentKeysForUser
549
+ ) ;
550
+ } )
551
+ ) ;
552
+ } ) ;
553
+ } )
554
+ . next ( ( ) => PersistencePromise . waitFor ( promises ) ) ;
555
+ }
458
556
}
459
557
460
558
function sentinelKey ( path : ResourcePath ) : DbTargetDocumentKey {
0 commit comments