Skip to content

Commit a1b7467

Browse files
authored
Merge d03f9b0 into 1a06d5d
2 parents 1a06d5d + d03f9b0 commit a1b7467

22 files changed

+1863
-256
lines changed

packages/firestore/src/local/document_overlay_cache.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ export interface DocumentOverlayCache {
4343
key: DocumentKey
4444
): PersistencePromise<Overlay | null>;
4545

46+
/**
47+
* Gets the saved overlay mutation for the given document keys. Skips keys for
48+
* which there are no overlays.
49+
*/
50+
getOverlays(
51+
transaction: PersistenceTransaction,
52+
keys: DocumentKeySet
53+
): PersistencePromise<OverlayMap>;
54+
4655
/**
4756
* Saves the given document mutation map to persistence as overlays.
4857
* All overlays will have their largest batch id set to `largestBatchId`.

packages/firestore/src/local/indexeddb_document_overlay_cache.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@ export class IndexedDbDocumentOverlayCache implements DocumentOverlayCache {
8181
});
8282
}
8383

84+
getOverlays(
85+
transaction: PersistenceTransaction,
86+
keys: DocumentKeySet
87+
): PersistencePromise<OverlayMap> {
88+
const result = newOverlayMap();
89+
const promises: Array<PersistencePromise<void>> = [];
90+
keys.forEach(key => {
91+
promises.push(
92+
this.getOverlay(transaction, key).next(overlay => {
93+
if (overlay !== null) {
94+
result.set(key, overlay);
95+
}
96+
})
97+
);
98+
});
99+
return PersistencePromise.waitFor(promises).next(() => result);
100+
}
101+
84102
saveOverlays(
85103
transaction: PersistenceTransaction,
86104
largestBatchId: number,

packages/firestore/src/local/indexeddb_schema.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { DbTimestampKey } from './indexeddb_sentinels';
3131
// TODO(indexing): Remove this constant
3232
export const INDEXING_ENABLED = false;
3333

34-
export const INDEXING_SCHEMA_VERSION = 14;
34+
export const INDEXING_SCHEMA_VERSION = 15;
3535

3636
/**
3737
* Schema Version for the Web client:
@@ -54,10 +54,11 @@ export const INDEXING_SCHEMA_VERSION = 14;
5454
* 12. Add document overlays.
5555
* 13. Rewrite the keys of the remote document cache to allow for efficient
5656
* document lookup via `getAll()`.
57-
* 14. Add indexing support.
57+
* 14. Add overlays.
58+
* 15. Add indexing support.
5859
*/
5960

60-
export const SCHEMA_VERSION = INDEXING_ENABLED ? INDEXING_SCHEMA_VERSION : 13;
61+
export const SCHEMA_VERSION = INDEXING_ENABLED ? INDEXING_SCHEMA_VERSION : 14;
6162

6263
/**
6364
* Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.

packages/firestore/src/local/indexeddb_schema_converter.ts

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@
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 {
22+
DocumentKeyMap,
23+
DocumentKeySet,
24+
documentKeySet
25+
} from '../model/collections';
1926
import { DocumentKey } from '../model/document_key';
27+
import { FieldMask } from '../model/field_mask';
2028
import { ResourcePath } from '../model/path';
2129
import { debugAssert, fail, hardAssert } from '../util/assert';
2230
import { BATCHID_UNKNOWN } from '../util/types';
@@ -25,10 +33,13 @@ import {
2533
decodeResourcePath,
2634
encodeResourcePath
2735
} from './encoded_resource_path';
36+
import { IndexedDbDocumentOverlayCache } from './indexeddb_document_overlay_cache';
2837
import {
2938
dbDocumentSize,
3039
removeMutationBatch
3140
} from './indexeddb_mutation_batch_impl';
41+
import { IndexedDbMutationQueue } from './indexeddb_mutation_queue';
42+
import { newIndexedDbRemoteDocumentCache } from './indexeddb_remote_document_cache';
3243
import {
3344
DbCollectionParent,
3445
DbDocumentMutation,
@@ -107,13 +118,16 @@ import {
107118
DbTargetQueryTargetsKeyPath,
108119
DbTargetStore
109120
} from './indexeddb_sentinels';
121+
import { IndexedDbTransaction } from './indexeddb_transaction';
122+
import { LocalDocumentsView } from './local_documents_view';
110123
import {
111124
fromDbMutationBatch,
112125
fromDbTarget,
113126
LocalSerializer,
114127
toDbTarget
115128
} from './local_serializer';
116129
import { MemoryCollectionParentIndex } from './memory_index_manager';
130+
import { MemoryEagerDelegate, MemoryPersistence } from './memory_persistence';
117131
import { PersistencePromise } from './persistence_promise';
118132
import { SimpleDbSchemaConverter, SimpleDbTransaction } from './simple_db';
119133

@@ -240,9 +254,11 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
240254
}
241255

242256
if (fromVersion < 14 && toVersion >= 14) {
243-
p = p.next(() => {
244-
createFieldIndex(db);
245-
});
257+
p = p.next(() => this.runOverlayMigration(db, simpleDbTransaction));
258+
}
259+
260+
if (fromVersion < 15 && toVersion >= 15) {
261+
p = p.next(() => createFieldIndex(db));
246262
}
247263

248264
return p;
@@ -455,6 +471,74 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
455471
})
456472
.next(() => PersistencePromise.waitFor(writes));
457473
}
474+
475+
private runOverlayMigration(
476+
db: IDBDatabase,
477+
transaction: SimpleDbTransaction
478+
): PersistencePromise<void> {
479+
const mutationsStore = transaction.store<
480+
DbMutationBatchKey,
481+
DbMutationBatch
482+
>(DbMutationBatchStore);
483+
484+
const remoteDocumentCache = newIndexedDbRemoteDocumentCache(
485+
this.serializer
486+
);
487+
const memoryPersistence = new MemoryPersistence(
488+
MemoryEagerDelegate.factory,
489+
this.serializer.remoteSerializer
490+
);
491+
492+
const promises: Array<
493+
PersistencePromise<DocumentKeyMap<FieldMask | null>>
494+
> = [];
495+
const userToDocumentSet = new Map<string, DocumentKeySet>();
496+
497+
return mutationsStore
498+
.loadAll()
499+
.next(dbBatches => {
500+
dbBatches.forEach(dbBatch => {
501+
let documentSet =
502+
userToDocumentSet.get(dbBatch.userId) ?? documentKeySet();
503+
const batch = fromDbMutationBatch(this.serializer, dbBatch);
504+
batch.keys().forEach(key => (documentSet = documentSet.add(key)));
505+
userToDocumentSet.set(dbBatch.userId, documentSet);
506+
});
507+
})
508+
.next(() => {
509+
userToDocumentSet.forEach((allDocumentKeysForUser, userId) => {
510+
const user = new User(userId);
511+
const documentOverlayCache = IndexedDbDocumentOverlayCache.forUser(
512+
this.serializer,
513+
user
514+
);
515+
// NOTE: The index manager and the reference delegate are
516+
// irrelevant for the purpose of recalculating and saving
517+
// overlays. We can therefore simply use the memory
518+
// implementation.
519+
const indexManager = memoryPersistence.getIndexManager(user);
520+
const mutationQueue = IndexedDbMutationQueue.forUser(
521+
user,
522+
this.serializer,
523+
indexManager,
524+
memoryPersistence.referenceDelegate
525+
);
526+
const localDocumentsView = new LocalDocumentsView(
527+
remoteDocumentCache,
528+
mutationQueue,
529+
documentOverlayCache,
530+
indexManager
531+
);
532+
promises.push(
533+
localDocumentsView.recalculateAndSaveOverlaysForDocumentKeys(
534+
new IndexedDbTransaction(transaction, ListenSequence.INVALID),
535+
allDocumentKeysForUser
536+
)
537+
);
538+
});
539+
})
540+
.next(() => PersistencePromise.waitFor(promises));
541+
}
458542
}
459543

460544
function sentinelKey(path: ResourcePath): DbTargetDocumentKey {

packages/firestore/src/local/indexeddb_sentinels.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,9 @@ export const V13_STORES = [
407407
DbNamedQueryStore,
408408
DbDocumentOverlayStore
409409
];
410-
export const V14_STORES = [
411-
...V13_STORES,
410+
export const V14_STORES = V13_STORES;
411+
export const V15_STORES = [
412+
...V14_STORES,
412413
DbIndexConfigurationStore,
413414
DbIndexStateStore,
414415
DbIndexEntryStore
@@ -423,7 +424,9 @@ export const ALL_STORES = V12_STORES;
423424

424425
/** Returns the object stores for the provided schema. */
425426
export function getObjectStores(schemaVersion: number): string[] {
426-
if (schemaVersion === 14) {
427+
if (schemaVersion === 15) {
428+
return V15_STORES;
429+
} else if (schemaVersion === 14) {
427430
return V14_STORES;
428431
} else if (schemaVersion === 13) {
429432
return V13_STORES;

0 commit comments

Comments
 (0)