aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Source/Core
diff options
context:
space:
mode:
authorGravatar rsgowman <rgowman@google.com>2018-04-18 10:30:37 -0400
committerGravatar GitHub <noreply@github.com>2018-04-18 10:30:37 -0400
commita5b3185ed372fc16b5430c230c197e3dbd34f953 (patch)
tree8f77610cf27ee35f5cccad825b6a33e74d7be8ef /Firestore/Source/Core
parent6a39c71be83f589550c7dfa3c6d89d8b6145887c (diff)
Add GetOptions for controlling offline get behaviour (#655)
Add option to allow the user to control where DocumentReference.getDocument() and CollectionReference.getDocuments() fetches from. By default, it fetches from the server (if possible) and falls back to the local cache. It's now possible to alternatively fetch from the local cache only, or to fetch from the server only (though in the server only case, latency compensation is still enabled).
Diffstat (limited to 'Firestore/Source/Core')
-rw-r--r--Firestore/Source/Core/FSTFirestoreClient.h22
-rw-r--r--Firestore/Source/Core/FSTFirestoreClient.mm63
2 files changed, 85 insertions, 0 deletions
diff --git a/Firestore/Source/Core/FSTFirestoreClient.h b/Firestore/Source/Core/FSTFirestoreClient.h
index 6da5ed3..7285e65 100644
--- a/Firestore/Source/Core/FSTFirestoreClient.h
+++ b/Firestore/Source/Core/FSTFirestoreClient.h
@@ -24,6 +24,12 @@
#include "Firestore/core/src/firebase/firestore/core/database_info.h"
#include "Firestore/core/src/firebase/firestore/model/database_id.h"
+@class FIRDocumentReference;
+@class FIRDocumentSnapshot;
+@class FIRQuery;
+@class FIRQuerySnapshot;
+@class FSTDatabaseID;
+@class FSTDatabaseInfo;
@class FSTDispatchQueue;
@class FSTDocument;
@class FSTListenOptions;
@@ -72,6 +78,22 @@ NS_ASSUME_NONNULL_BEGIN
/** Stops listening to a query previously listened to. */
- (void)removeListener:(FSTQueryListener *)listener;
+/**
+ * Retrieves a document from the cache via the indicated completion. If the doc
+ * doesn't exist, an error will be sent to the completion.
+ */
+- (void)getDocumentFromLocalCache:(FIRDocumentReference *)doc
+ completion:(void (^)(FIRDocumentSnapshot *_Nullable document,
+ NSError *_Nullable error))completion;
+
+/**
+ * Retrieves a (possibly empty) set of documents from the cache via the
+ * indicated completion.
+ */
+- (void)getDocumentsFromLocalCache:(FIRQuery *)query
+ completion:(void (^)(FIRQuerySnapshot *_Nullable query,
+ NSError *_Nullable error))completion;
+
/** Write mutations. completion will be notified when it's written to the backend. */
- (void)writeMutations:(NSArray<FSTMutation *> *)mutations
completion:(nullable FSTVoidErrorBlock)completion;
diff --git a/Firestore/Source/Core/FSTFirestoreClient.mm b/Firestore/Source/Core/FSTFirestoreClient.mm
index 33d1903..4f1a20b 100644
--- a/Firestore/Source/Core/FSTFirestoreClient.mm
+++ b/Firestore/Source/Core/FSTFirestoreClient.mm
@@ -19,15 +19,25 @@
#include <future> // NOLINT(build/c++11)
#include <memory>
+#import "FIRFirestoreErrors.h"
+#import "Firestore/Source/API/FIRDocumentReference+Internal.h"
+#import "Firestore/Source/API/FIRDocumentSnapshot+Internal.h"
+#import "Firestore/Source/API/FIRQuery+Internal.h"
+#import "Firestore/Source/API/FIRQuerySnapshot+Internal.h"
+#import "Firestore/Source/API/FIRSnapshotMetadata+Internal.h"
#import "Firestore/Source/Core/FSTEventManager.h"
+#import "Firestore/Source/Core/FSTQuery.h"
#import "Firestore/Source/Core/FSTSyncEngine.h"
#import "Firestore/Source/Core/FSTTransaction.h"
+#import "Firestore/Source/Core/FSTView.h"
#import "Firestore/Source/Local/FSTEagerGarbageCollector.h"
#import "Firestore/Source/Local/FSTLevelDB.h"
#import "Firestore/Source/Local/FSTLocalSerializer.h"
#import "Firestore/Source/Local/FSTLocalStore.h"
#import "Firestore/Source/Local/FSTMemoryPersistence.h"
#import "Firestore/Source/Local/FSTNoOpGarbageCollector.h"
+#import "Firestore/Source/Model/FSTDocument.h"
+#import "Firestore/Source/Model/FSTDocumentSet.h"
#import "Firestore/Source/Remote/FSTDatastore.h"
#import "Firestore/Source/Remote/FSTRemoteStore.h"
#import "Firestore/Source/Remote/FSTSerializerBeta.h"
@@ -271,6 +281,59 @@ NS_ASSUME_NONNULL_BEGIN
}];
}
+- (void)getDocumentFromLocalCache:(FIRDocumentReference *)doc
+ completion:(void (^)(FIRDocumentSnapshot *_Nullable document,
+ NSError *_Nullable error))completion {
+ [self.workerDispatchQueue dispatchAsync:^{
+ FSTMaybeDocument *maybeDoc = [self.localStore readDocument:doc.key];
+ if (maybeDoc) {
+ completion([FIRDocumentSnapshot snapshotWithFirestore:doc.firestore
+ documentKey:doc.key
+ document:(FSTDocument *)maybeDoc
+ fromCache:YES],
+ nil);
+ } else {
+ completion(nil,
+ [NSError errorWithDomain:FIRFirestoreErrorDomain
+ code:FIRFirestoreErrorCodeUnavailable
+ userInfo:@{
+ NSLocalizedDescriptionKey :
+ @"Failed to get document from cache. (However, this "
+ @"document may exist on the server. Run again without "
+ @"setting source to FIRFirestoreSourceCache to attempt to "
+ @"retrieve the document from the server.)",
+ }]);
+ }
+ }];
+}
+
+- (void)getDocumentsFromLocalCache:(FIRQuery *)query
+ completion:(void (^)(FIRQuerySnapshot *_Nullable query,
+ NSError *_Nullable error))completion {
+ [self.workerDispatchQueue dispatchAsync:^{
+
+ FSTDocumentDictionary *docs = [self.localStore executeQuery:query.query];
+ FSTDocumentKeySet *remoteKeys = [FSTDocumentKeySet keySet];
+
+ FSTView *view = [[FSTView alloc] initWithQuery:query.query remoteDocuments:remoteKeys];
+ FSTViewDocumentChanges *viewDocChanges = [view computeChangesWithDocuments:docs];
+ FSTViewChange *viewChange = [view applyChangesToDocuments:viewDocChanges];
+ FSTAssert(viewChange.limboChanges.count == 0,
+ @"View returned limbo documents during local-only query execution.");
+
+ FSTViewSnapshot *snapshot = viewChange.snapshot;
+ FIRSnapshotMetadata *metadata =
+ [FIRSnapshotMetadata snapshotMetadataWithPendingWrites:snapshot.hasPendingWrites
+ fromCache:snapshot.fromCache];
+
+ completion([FIRQuerySnapshot snapshotWithFirestore:query.firestore
+ originalQuery:query.query
+ snapshot:snapshot
+ metadata:metadata],
+ nil);
+ }];
+}
+
- (void)writeMutations:(NSArray<FSTMutation *> *)mutations
completion:(nullable FSTVoidErrorBlock)completion {
[self.workerDispatchQueue dispatchAsync:^{