Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save schmidt-sebastian/932ffd496e1129309b9d6b4861d2c879 to your computer and use it in GitHub Desktop.
Save schmidt-sebastian/932ffd496e1129309b9d6b4861d2c879 to your computer and use it in GitHub Desktop.
diff --git a/packages/firestore/src/local/local_store.ts b/packages/firestore/src/local/local_store.ts
index cddfa5b01..af9cb9998 100644
--- a/packages/firestore/src/local/local_store.ts
+++ b/packages/firestore/src/local/local_store.ts
@@ -95,6 +95,14 @@ export interface QueryResult {
readonly remoteKeys: DocumentKeySet;
}
+class LocalStoreImpl {
+ // TODO: Move persistence here
+ protected constructor(
+ readonly serializer: JsonProtoSerializer,
+ readonly remoteDocuments: RemoteDocumentCache
+ ) {}
+}
+
/**
* Local storage in the Firestore client. Coordinates persistence components
* like the mutation queue and remote document cache to present a
@@ -146,7 +154,7 @@ export interface QueryResult {
* (unexpected) failure (e.g. failed assert) and always represent an
* unrecoverable error (should be caught / reported by the async_queue).
*/
-export class LocalStore {
+export class LocalStore extends LocalStoreImpl {
/**
* The maximum time to leave a resume token buffered without writing it out.
* This value is arbitrary: it's long enough to avoid several writes
@@ -162,9 +170,6 @@ export class LocalStore {
*/
protected mutationQueue: MutationQueue;
- /** The set of all cached remote documents. */
- protected remoteDocuments: RemoteDocumentCache;
-
/**
* The "local" view of all documents (layering mutationQueue on top of
* remoteDocumentCache).
@@ -200,21 +205,20 @@ export class LocalStore {
*/
protected lastDocumentChangeReadTime = SnapshotVersion.min();
- private bundleConverter: BundleConverter;
-
constructor(
/** Manages our in-memory or durable persistence. */
protected persistence: Persistence,
private queryEngine: QueryEngine,
initialUser: User,
- private serializer: JsonProtoSerializer
+ serializer: JsonProtoSerializer
) {
+ super(serializer, persistence.getRemoteDocumentCache());
+
debugAssert(
persistence.started,
'LocalStore was passed an unstarted persistence implementation'
);
this.mutationQueue = persistence.getMutationQueue(initialUser);
- this.remoteDocuments = persistence.getRemoteDocumentCache();
this.targetCache = persistence.getTargetCache();
this.bundleCache = persistence.getBundleCache();
this.localDocuments = new LocalDocumentsView(
@@ -223,8 +227,6 @@ export class LocalStore {
this.persistence.getIndexManager()
);
this.queryEngine.setLocalDocumentsView(this.localDocuments);
-
- this.bundleConverter = new BundleConverter(this.serializer);
}
/** Starts the LocalStore. */
@@ -618,58 +620,6 @@ export class LocalStore {
});
}
- /**
- * Applies the documents from a bundle to the "ground-state" (remote)
- * documents.
- *
- * LocalDocuments are re-calculated if there are remaining mutations in the
- * queue.
- */
- applyBundleDocuments(documents: BundledDocuments): Promise<MaybeDocumentMap> {
- let documentMap = maybeDocumentMap();
- let versionMap = documentVersionMap();
- for (const bundleDoc of documents) {
- const documentKey = this.bundleConverter.toDocumentKey(
- bundleDoc.metadata.name!
- );
- documentMap = documentMap.insert(
- documentKey,
- this.bundleConverter.toMaybeDocument(bundleDoc)
- );
- versionMap = versionMap.insert(
- documentKey,
- this.bundleConverter.toSnapshotVersion(bundleDoc.metadata.readTime!)
- );
- }
-
- const documentBuffer = this.remoteDocuments.newChangeBuffer({
- trackRemovals: true // Make sure document removals show up in `getNewDocumentChanges()`
- });
- return this.persistence.runTransaction(
- 'Apply bundle documents',
- 'readwrite-primary',
- txn => {
- return this.applyDocuments(
- txn,
- documentBuffer,
- documentMap,
- undefined,
- versionMap
- )
- .next(changedDocs => {
- documentBuffer.apply(txn);
- return changedDocs;
- })
- .next(changedDocs => {
- return this.localDocuments.getLocalViewOfDocuments(
- txn,
- changedDocs
- );
- });
- }
- );
- }
-
/**
* Applies documents to remote document cache, returns the document changes
* resulting from applying those documents.
@@ -742,40 +692,6 @@ export class LocalStore {
});
}
- /**
- * Returns a promise of a boolean to indicate if the given bundle has already
- * been loaded and the create time is newer than the current loading bundle.
- */
- hasNewerBundle(bundleMetadata: bundleProto.BundleMetadata): Promise<boolean> {
- const currentReadTime = this.bundleConverter.toSnapshotVersion(
- bundleMetadata.createTime!
- );
- return this.persistence
- .runTransaction('isNewerBundleLoaded', 'readonly', transaction => {
- return this.bundleCache.getBundleMetadata(
- transaction,
- bundleMetadata.id!
- );
- })
- .then(cached => {
- return !!cached && cached.createTime!.compareTo(currentReadTime) > 0;
- });
- }
-
- /**
- * Saves the given `BundleMetadata` to local persistence.
- * @param bundleMetadata
- */
- saveBundle(bundleMetadata: bundleProto.BundleMetadata): Promise<void> {
- return this.persistence.runTransaction(
- 'Save bundle',
- 'readwrite',
- transaction => {
- return this.bundleCache.saveBundleMetadata(transaction, bundleMetadata);
- }
- );
- }
-
/**
* Returns a promise of a `NamedQuery` associated with given query name. Promise
* resolves to undefined if no persisted data can be found.
@@ -1159,7 +1075,7 @@ export class LocalStore {
// PORTING NOTE: Web only.
export class MultiTabLocalStore extends LocalStore {
protected mutationQueue: IndexedDbMutationQueue;
- protected remoteDocuments: IndexedDbRemoteDocumentCache;
+ remoteDocuments: IndexedDbRemoteDocumentCache;
protected targetCache: IndexedDbTargetCache;
constructor(
@@ -1171,6 +1087,7 @@ export class MultiTabLocalStore extends LocalStore {
super(persistence, queryEngine, initialUser, serializer);
this.mutationQueue = persistence.getMutationQueue(initialUser);
+ // TODO: Plumb this through the constructor
this.remoteDocuments = persistence.getRemoteDocumentCache();
this.targetCache = persistence.getTargetCache();
}
@@ -1288,3 +1205,98 @@ export async function ignoreIfPrimaryLeaseLoss(
throw err;
}
}
+
+/**
+ * Applies the documents from a bundle to the "ground-state" (remote)
+ * documents.
+ *
+ * LocalDocuments are re-calculated if there are remaining mutations in the
+ * queue.
+ */
+function applyBundleDocuments(
+ localStore: LocalStore,
+ documents: BundledDocuments
+): Promise<MaybeDocumentMap> {
+ const bundleConverter = new BundleConverter(localStore.serializer);
+
+ let documentMap = maybeDocumentMap();
+ let versionMap = documentVersionMap();
+ for (const bundleDoc of documents) {
+ const documentKey = bundleConverter.toDocumentKey(bundleDoc.metadata.name!);
+ documentMap = documentMap.insert(
+ documentKey,
+ bundleConverter.toMaybeDocument(bundleDoc)
+ );
+ versionMap = versionMap.insert(
+ documentKey,
+ bundleConverter.toSnapshotVersion(bundleDoc.metadata.readTime!)
+ );
+ }
+
+ const documentBuffer = localStore.remoteDocuments.newChangeBuffer({
+ trackRemovals: true // Make sure document removals show up in `getNewDocumentChanges()`
+ });
+ return this.persistence.runTransaction(
+ 'Apply bundle documents',
+ 'readwrite-primary',
+ txn => {
+ return this.applyDocuments(
+ txn,
+ documentBuffer,
+ documentMap,
+ undefined,
+ versionMap
+ )
+ .next(changedDocs => {
+ documentBuffer.apply(txn);
+ return changedDocs;
+ })
+ .next(changedDocs => {
+ return this.localDocuments.getLocalViewOfDocuments(txn, changedDocs);
+ });
+ }
+ );
+}
+
+/**
+ * Returns a promise of a boolean to indicate if the given bundle has already
+ * been loaded and the create time is newer than the current loading bundle.
+ */
+function hasNewerBundle(
+ localStore: LocalStore,
+ bundleMetadata: bundleProto.BundleMetadata
+): Promise<boolean> {
+ const currentReadTime = this.bundleConverter.toSnapshotVersion(
+ bundleMetadata.createTime!
+ );
+ return this.persistence
+ .runTransaction('isNewerBundleLoaded', 'readonly', transaction => {
+ return this.bundleCache.getBundleMetadata(
+ transaction,
+ bundleMetadata.id!
+ );
+ })
+ .then(cached => {
+ return !!cached && cached.createTime!.compareTo(currentReadTime) > 0;
+ });
+}
+
+/**
+ * Saves the given `BundleMetadata` to local persistence.
+ * @param bundleMetadata
+ */
+function saveBundle(
+ localStore: LocalStore,
+ bundleMetadata: bundleProto.BundleMetadata
+): Promise<void> {
+ return localStore.persistence.runTransaction(
+ 'Save bundle',
+ 'readwrite',
+ transaction => {
+ return localStore.bundleCache.saveBundleMetadata(
+ transaction,
+ bundleMetadata
+ );
+ }
+ );
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment