Created
June 18, 2020 17:57
-
-
Save schmidt-sebastian/932ffd496e1129309b9d6b4861d2c879 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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