diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index 0e01dfef9e7..9a07ef3ada9 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -54,7 +54,8 @@ export const INDEXING_SCHEMA_VERSION = 15; * 12. Add document overlays. * 13. Rewrite the keys of the remote document cache to allow for efficient * document lookup via `getAll()`. - * 14. Add indexing support. + * 14. Add overlays. + * 15. Add indexing support. */ export const SCHEMA_VERSION = INDEXING_ENABLED ? INDEXING_SCHEMA_VERSION : 14; diff --git a/packages/firestore/src/local/indexeddb_schema_converter.ts b/packages/firestore/src/local/indexeddb_schema_converter.ts index 873060ab858..700d12de32c 100644 --- a/packages/firestore/src/local/indexeddb_schema_converter.ts +++ b/packages/firestore/src/local/indexeddb_schema_converter.ts @@ -18,7 +18,7 @@ import { User } from '../auth/user'; import { ListenSequence } from '../core/listen_sequence'; import { SnapshotVersion } from '../core/snapshot_version'; -import { documentKeySet } from '../model/collections'; +import { DocumentKeySet, documentKeySet } from '../model/collections'; import { DocumentKey } from '../model/document_key'; import { ResourcePath } from '../model/path'; import { debugAssert, fail, hardAssert } from '../util/assert'; @@ -471,9 +471,6 @@ export class SchemaConverter implements SimpleDbSchemaConverter { db: IDBDatabase, transaction: SimpleDbTransaction ): PersistencePromise { - const queuesStore = transaction.store( - DbMutationQueueStore - ); const mutationsStore = transaction.store< DbMutationBatchKey, DbMutationBatch @@ -482,78 +479,56 @@ export class SchemaConverter implements SimpleDbSchemaConverter { const remoteDocumentCache = newIndexedDbRemoteDocumentCache( this.serializer ); + const memoryPersistence = new MemoryPersistence( + MemoryEagerDelegate.factory, + this.serializer.remoteSerializer + ); const promises: Array> = []; - let userIds = new Set(); + const userToDocumentSet = new Map(); - return queuesStore + return mutationsStore .loadAll() - .next(queues => { - for (const queue of queues) { - const userId = queue.userId; - if (userIds.has(userId)) { - // We have already processed this user. - continue; - } - userIds = userIds.add(userId); + .next(dbBatches => { + dbBatches.forEach(dbBatch => { + let documentSet = + userToDocumentSet.get(dbBatch.userId) ?? documentKeySet(); + const batch = fromDbMutationBatch(this.serializer, dbBatch); + batch.keys().forEach(key => (documentSet = documentSet.add(key))); + userToDocumentSet.set(dbBatch.userId, documentSet); + }); + }) + .next(() => { + userToDocumentSet.forEach((allDocumentKeysForUser, userId) => { const user = new User(userId); const documentOverlayCache = IndexedDbDocumentOverlayCache.forUser( this.serializer, user ); - let allDocumentKeysForUser = documentKeySet(); - const range = IDBKeyRange.bound( - [userId, BATCHID_UNKNOWN], - [userId, Number.POSITIVE_INFINITY] + // NOTE: The index manager and the reference delegate are + // irrelevant for the purpose of recalculating and saving + // overlays. We can therefore simply use the memory + // implementation. + const indexManager = memoryPersistence.getIndexManager(user); + const mutationQueue = IndexedDbMutationQueue.forUser( + user, + this.serializer, + indexManager, + memoryPersistence.referenceDelegate + ); + const localDocumentsView = new LocalDocumentsView( + remoteDocumentCache, + mutationQueue, + documentOverlayCache, + indexManager ); promises.push( - mutationsStore - .loadAll(DbMutationBatchUserMutationsIndex, range) - .next(dbBatches => { - dbBatches.forEach(dbBatch => { - hardAssert( - dbBatch.userId === userId, - `Cannot process batch ${dbBatch.batchId} from unexpected user` - ); - const batch = fromDbMutationBatch(this.serializer, dbBatch); - batch - .keys() - .forEach( - key => - (allDocumentKeysForUser = - allDocumentKeysForUser.add(key)) - ); - }); - }) - .next(() => { - // NOTE: The index manager and the reference delegate are - // irrelevant for the purpose of recalculating and saving - // overlays. We can therefore simply use the memory - // implementation. - const memoryPersistence = new MemoryPersistence( - MemoryEagerDelegate.factory, - this.serializer.remoteSerializer - ); - const indexManager = memoryPersistence.getIndexManager(user); - const mutationQueue = IndexedDbMutationQueue.forUser( - user, - this.serializer, - indexManager, - memoryPersistence.referenceDelegate - ); - const localDocumentsView = new LocalDocumentsView( - remoteDocumentCache, - mutationQueue, - documentOverlayCache, - indexManager - ); - return localDocumentsView.recalculateAndSaveOverlaysForDocumentKeys( - new IndexedDbTransaction(transaction, ListenSequence.INVALID), - allDocumentKeysForUser - ); - }) + localDocumentsView.recalculateAndSaveOverlaysForDocumentKeys( + new IndexedDbTransaction(transaction, ListenSequence.INVALID), + allDocumentKeysForUser + ) ); - } + }); }) .next(() => PersistencePromise.waitFor(promises)); } diff --git a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts index 2528e8121ca..02b35d125aa 100644 --- a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts +++ b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts @@ -1138,11 +1138,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { DbDocumentMutationKey, DbDocumentMutation >(DbDocumentMutationStore); - const mutationQueuesStore = txn.store< - DbMutationQueueKey, - DbMutationQueue - >(DbMutationQueueStore); - // Manually populate the mutation queue and create all indicies. + // Manually populate the mutations. return PersistencePromise.forEach( testMutations, (testMutation: DbMutationBatch) => { @@ -1163,25 +1159,6 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { ); }); } - ).next(() => - // Populate the mutation queues' metadata - PersistencePromise.waitFor([ - mutationQueuesStore.put({ - userId: 'user1', - lastAcknowledgedBatchId: -1, - lastStreamToken: '' - }), - mutationQueuesStore.put({ - userId: 'user2', - lastAcknowledgedBatchId: -1, - lastStreamToken: '' - }), - mutationQueuesStore.put({ - userId: 'user3', - lastAcknowledgedBatchId: -1, - lastStreamToken: '' - }) - ]) ); } ); @@ -1202,7 +1179,6 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { // We should have a total of 4 overlays: // For user1: testWriteFoo // For user2: testWriteBar, testWriteBaz, and testWritePending - // For user3: NO OVERLAYS! let p = documentOverlayStore.count().next(count => { expect(count).to.equal(4); });