Skip to content

Commit 0a979d0

Browse files
committed
Overlay migration
1 parent 104964e commit 0a979d0

File tree

1 file changed

+101
-3
lines changed

1 file changed

+101
-3
lines changed

packages/firestore/src/local/indexeddb_schema_converter.ts

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { User } from '../auth/user';
19+
import { ListenSequence } from '../core/listen_sequence';
1820
import { SnapshotVersion } from '../core/snapshot_version';
21+
import { documentKeySet } from '../model/collections';
1922
import { DocumentKey } from '../model/document_key';
2023
import { ResourcePath } from '../model/path';
2124
import { debugAssert, fail, hardAssert } from '../util/assert';
@@ -25,10 +28,13 @@ import {
2528
decodeResourcePath,
2629
encodeResourcePath
2730
} from './encoded_resource_path';
31+
import { IndexedDbDocumentOverlayCache } from './indexeddb_document_overlay_cache';
2832
import {
2933
dbDocumentSize,
3034
removeMutationBatch
3135
} from './indexeddb_mutation_batch_impl';
36+
import { IndexedDbMutationQueue } from './indexeddb_mutation_queue';
37+
import { newIndexedDbRemoteDocumentCache } from './indexeddb_remote_document_cache';
3238
import {
3339
DbCollectionParent,
3440
DbDocumentMutation,
@@ -107,13 +113,16 @@ import {
107113
DbTargetQueryTargetsKeyPath,
108114
DbTargetStore
109115
} from './indexeddb_sentinels';
116+
import { IndexedDbTransaction } from './indexeddb_transaction';
117+
import { LocalDocumentsView } from './local_documents_view';
110118
import {
111119
fromDbMutationBatch,
112120
fromDbTarget,
113121
LocalSerializer,
114122
toDbTarget
115123
} from './local_serializer';
116124
import { MemoryCollectionParentIndex } from './memory_index_manager';
125+
import { MemoryEagerDelegate, MemoryPersistence } from './memory_persistence';
117126
import { PersistencePromise } from './persistence_promise';
118127
import { SimpleDbSchemaConverter, SimpleDbTransaction } from './simple_db';
119128

@@ -240,9 +249,9 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
240249
}
241250

242251
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));
246255
}
247256

248257
return p;
@@ -455,6 +464,95 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
455464
})
456465
.next(() => PersistencePromise.waitFor(writes));
457466
}
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+
}
458556
}
459557

460558
function sentinelKey(path: ResourcePath): DbTargetDocumentKey {

0 commit comments

Comments
 (0)