Skip to content

Commit e8b9ec2

Browse files
authored
Implement bundle features in local store. (#3200)
* Renaming interfaces without leading I * Initial commit of bundle reading - for web only. * Tests only run when it is not Node. * Fix redundant imports * Fix missing textencoder * Remove generator. * Support bundle reader for Node * Fix rebase errors. * Remote 'only' * Merge branch 'wuandy/Bundles' into wuandy/BundleReaderNode # Conflicts: # packages/firestore/src/util/bundle_reader.ts # packages/firestore/test/unit/util/bundle.test.ts * Added more comments, and more tests for Node. * Implement BundleCache. * Add applyBundleDocuments to local store. * Add rest of bundle service to localstore Fix change buffer bug * Simplify change buffer get read time logic. * Fix lint errors * Add comments. * Change localstore to check for newer bundle directly. * A little more comments. * Address comments. * Address comments 2 * Make it tree-shakeable. * More comments addressing. * Another around of comments
1 parent 6c375b9 commit e8b9ec2

13 files changed

+592
-130
lines changed

packages/firestore/src/core/bundle.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
1717

1818
import { Query } from './query';
1919
import { SnapshotVersion } from './snapshot_version';
20+
import {
21+
fromDocument,
22+
fromName,
23+
fromVersion,
24+
JsonProtoSerializer
25+
} from '../remote/serializer';
26+
import * as bundleProto from '../protos/firestore_bundle_proto';
27+
import * as api from '../protos/firestore_proto_api';
28+
import { DocumentKey } from '../model/document_key';
29+
import { MaybeDocument, NoDocument } from '../model/document';
30+
import { debugAssert } from '../util/assert';
2031

2132
/**
2233
* Represents a Firestore bundle saved by the SDK in its local storage.
@@ -40,3 +51,50 @@ export interface NamedQuery {
4051
/** The time at which the results for this query were read. */
4152
readonly readTime: SnapshotVersion;
4253
}
54+
55+
/**
56+
* Represents a bundled document, including the metadata and the document
57+
* itself, if it exists.
58+
*/
59+
interface BundledDocument {
60+
metadata: bundleProto.BundledDocumentMetadata;
61+
document: api.Document | undefined;
62+
}
63+
64+
/**
65+
* An array of `BundledDocument`.
66+
*/
67+
export type BundledDocuments = BundledDocument[];
68+
69+
/**
70+
* Helper to convert objects from bundles to model objects in the SDK.
71+
*/
72+
export class BundleConverter {
73+
constructor(private serializer: JsonProtoSerializer) {}
74+
75+
toDocumentKey(name: string): DocumentKey {
76+
return fromName(this.serializer, name);
77+
}
78+
79+
/**
80+
* Converts a BundleDocument to a MaybeDocument.
81+
*/
82+
toMaybeDocument(bundledDoc: BundledDocument): MaybeDocument {
83+
if (bundledDoc.metadata.exists) {
84+
debugAssert(
85+
!!bundledDoc.document,
86+
'Document is undefined when metadata.exist is true.'
87+
);
88+
return fromDocument(this.serializer, bundledDoc.document!, false);
89+
} else {
90+
return new NoDocument(
91+
this.toDocumentKey(bundledDoc.metadata.name!),
92+
this.toSnapshotVersion(bundledDoc.metadata.readTime!)
93+
);
94+
}
95+
}
96+
97+
toSnapshotVersion(time: api.Timestamp): SnapshotVersion {
98+
return fromVersion(time);
99+
}
100+
}

packages/firestore/src/core/component_provider.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
import { newConnectivityMonitor } from '../platform/connection';
5050
import { newSerializer } from '../platform/serializer';
5151
import { getDocument, getWindow } from '../platform/dom';
52+
import { JsonProtoSerializer } from '../remote/serializer';
5253

5354
const MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE =
5455
'You are using the memory-only build of Firestore. Persistence support is ' +
@@ -96,7 +97,10 @@ export class MemoryComponentProvider implements ComponentProvider {
9697
remoteStore!: RemoteStore;
9798
eventManager!: EventManager;
9899

100+
serializer!: JsonProtoSerializer;
101+
99102
async initialize(cfg: ComponentConfiguration): Promise<void> {
103+
this.serializer = newSerializer(cfg.databaseInfo.databaseId);
100104
this.sharedClientState = this.createSharedClientState(cfg);
101105
this.persistence = this.createPersistence(cfg);
102106
await this.persistence.start();
@@ -134,7 +138,8 @@ export class MemoryComponentProvider implements ComponentProvider {
134138
return newLocalStore(
135139
this.persistence,
136140
new IndexFreeQueryEngine(),
137-
cfg.initialUser
141+
cfg.initialUser,
142+
this.serializer
138143
);
139144
}
140145

@@ -145,8 +150,7 @@ export class MemoryComponentProvider implements ComponentProvider {
145150
MEMORY_ONLY_PERSISTENCE_ERROR_MESSAGE
146151
);
147152
}
148-
const serializer = newSerializer(cfg.databaseInfo.databaseId);
149-
return new MemoryPersistence(MemoryEagerDelegate.factory, serializer);
153+
return new MemoryPersistence(MemoryEagerDelegate.factory, this.serializer);
150154
}
151155

152156
createRemoteStore(cfg: ComponentConfiguration): RemoteStore {
@@ -221,7 +225,8 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
221225
return newMultiTabLocalStore(
222226
this.persistence,
223227
new IndexFreeQueryEngine(),
224-
cfg.initialUser
228+
cfg.initialUser,
229+
this.serializer
225230
);
226231
}
227232

@@ -257,7 +262,6 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
257262
const persistenceKey = IndexedDbPersistence.buildStoragePrefix(
258263
cfg.databaseInfo
259264
);
260-
const serializer = newSerializer(cfg.databaseInfo.databaseId);
261265
return new IndexedDbPersistence(
262266
cfg.persistenceSettings.synchronizeTabs,
263267
persistenceKey,
@@ -266,7 +270,7 @@ export class IndexedDbComponentProvider extends MemoryComponentProvider {
266270
cfg.asyncQueue,
267271
getWindow(),
268272
getDocument(),
269-
serializer,
273+
this.serializer,
270274
this.sharedClientState,
271275
cfg.persistenceSettings.forceOwningTab
272276
);

packages/firestore/src/local/bundle_cache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface BundleCache {
2828
* Gets a saved `Bundle` for a given `bundleId`, returns undefined if
2929
* no bundles are found under the given id.
3030
*/
31-
getBundle(
31+
getBundleMetadata(
3232
transaction: PersistenceTransaction,
3333
bundleId: string
3434
): PersistencePromise<Bundle | undefined>;

packages/firestore/src/local/indexeddb_bundle_cache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { Bundle, NamedQuery } from '../core/bundle';
3939
export class IndexedDbBundleCache implements BundleCache {
4040
constructor(private serializer: LocalSerializer) {}
4141

42-
getBundle(
42+
getBundleMetadata(
4343
transaction: PersistenceTransaction,
4444
bundleId: string
4545
): PersistencePromise<Bundle | undefined> {

packages/firestore/src/local/indexeddb_remote_document_cache.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -451,21 +451,21 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache {
451451
primitiveComparator(l.canonicalString(), r.canonicalString())
452452
);
453453

454-
this.changes.forEach((key, maybeDocument) => {
454+
this.changes.forEach((key, documentChange) => {
455455
const previousSize = this.documentSizes.get(key);
456456
debugAssert(
457457
previousSize !== undefined,
458458
`Cannot modify a document that wasn't read (for ${key})`
459459
);
460-
if (maybeDocument) {
460+
if (documentChange.maybeDocument) {
461461
debugAssert(
462-
!this.readTime.isEqual(SnapshotVersion.min()),
462+
!this.getReadTime(key).isEqual(SnapshotVersion.min()),
463463
'Cannot add a document with a read time of zero'
464464
);
465465
const doc = toDbRemoteDocument(
466466
this.documentCache.serializer,
467-
maybeDocument,
468-
this.readTime
467+
documentChange.maybeDocument,
468+
this.getReadTime(key)
469469
);
470470
collectionParents = collectionParents.add(key.path.popLast());
471471

@@ -482,7 +482,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache {
482482
const deletedDoc = toDbRemoteDocument(
483483
this.documentCache.serializer,
484484
new NoDocument(key, SnapshotVersion.min()),
485-
this.readTime
485+
this.getReadTime(key)
486486
);
487487
promises.push(
488488
this.documentCache.addEntry(transaction, key, deletedDoc)

0 commit comments

Comments
 (0)