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