From a5b3185ed372fc16b5430c230c197e3dbd34f953 Mon Sep 17 00:00:00 2001 From: rsgowman Date: Wed, 18 Apr 2018 10:30:37 -0400 Subject: 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). --- Firestore/Source/API/FIRDocumentReference.mm | 25 +++++++++++++++++- Firestore/Source/API/FIRQuery.mm | 38 ++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 6 deletions(-) (limited to 'Firestore/Source/API') diff --git a/Firestore/Source/API/FIRDocumentReference.mm b/Firestore/Source/API/FIRDocumentReference.mm index 2423472..c2fc546 100644 --- a/Firestore/Source/API/FIRDocumentReference.mm +++ b/Firestore/Source/API/FIRDocumentReference.mm @@ -22,6 +22,7 @@ #include #import "FIRFirestoreErrors.h" +#import "FIRFirestoreSource.h" #import "FIRSnapshotMetadata.h" #import "Firestore/Source/API/FIRCollectionReference+Internal.h" #import "Firestore/Source/API/FIRDocumentReference+Internal.h" @@ -162,6 +163,17 @@ NS_ASSUME_NONNULL_BEGIN - (void)getDocumentWithCompletion:(void (^)(FIRDocumentSnapshot *_Nullable document, NSError *_Nullable error))completion { + return [self getDocumentWithSource:FIRFirestoreSourceDefault completion:completion]; +} + +- (void)getDocumentWithSource:(FIRFirestoreSource)source + completion:(void (^)(FIRDocumentSnapshot *_Nullable document, + NSError *_Nullable error))completion { + if (source == FIRFirestoreSourceCache) { + [self.firestore.client getDocumentFromLocalCache:self completion:completion]; + return; + } + FSTListenOptions *options = [[FSTListenOptions alloc] initWithIncludeQueryMetadataChanges:YES includeDocumentMetadataChanges:YES waitForSyncWhenOnline:YES]; @@ -188,7 +200,6 @@ NS_ASSUME_NONNULL_BEGIN // offline. // 2) Actually call the completion handler with an error if the document doesn't exist when // you are offline. - // TODO(dimond): Use proper error domain completion(nil, [NSError errorWithDomain:FIRFirestoreErrorDomain code:FIRFirestoreErrorCodeUnavailable @@ -196,6 +207,18 @@ NS_ASSUME_NONNULL_BEGIN NSLocalizedDescriptionKey : @"Failed to get document because the client is offline.", }]); + } else if (snapshot.exists && snapshot.metadata.fromCache && + source == FIRFirestoreSourceServer) { + completion(nil, + [NSError errorWithDomain:FIRFirestoreErrorDomain + code:FIRFirestoreErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : + @"Failed to get document from server. (However, this " + @"document does exist in the local cache. Run again " + @"without setting source to FIRFirestoreSourceServer to " + @"retrieve the cached document.)" + }]); } else { completion(snapshot, nil); } diff --git a/Firestore/Source/API/FIRQuery.mm b/Firestore/Source/API/FIRQuery.mm index 14dcaef..2d78ac0 100644 --- a/Firestore/Source/API/FIRQuery.mm +++ b/Firestore/Source/API/FIRQuery.mm @@ -17,6 +17,8 @@ #import "FIRQuery.h" #import "FIRDocumentReference.h" +#import "FIRFirestoreErrors.h" +#import "FIRFirestoreSource.h" #import "Firestore/Source/API/FIRDocumentReference+Internal.h" #import "Firestore/Source/API/FIRDocumentSnapshot+Internal.h" #import "Firestore/Source/API/FIRFieldPath+Internal.h" @@ -96,9 +98,21 @@ NS_ASSUME_NONNULL_BEGIN - (void)getDocumentsWithCompletion:(void (^)(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error))completion { - FSTListenOptions *options = [[FSTListenOptions alloc] initWithIncludeQueryMetadataChanges:YES - includeDocumentMetadataChanges:YES - waitForSyncWhenOnline:YES]; + [self getDocumentsWithSource:FIRFirestoreSourceDefault completion:completion]; +} + +- (void)getDocumentsWithSource:(FIRFirestoreSource)source + completion:(void (^)(FIRQuerySnapshot *_Nullable snapshot, + NSError *_Nullable error))completion { + if (source == FIRFirestoreSourceCache) { + [self.firestore.client getDocumentsFromLocalCache:self completion:completion]; + return; + } + + FSTListenOptions *listenOptions = + [[FSTListenOptions alloc] initWithIncludeQueryMetadataChanges:YES + includeDocumentMetadataChanges:YES + waitForSyncWhenOnline:YES]; dispatch_semaphore_t registered = dispatch_semaphore_create(0); __block id listenerRegistration; @@ -113,10 +127,24 @@ NS_ASSUME_NONNULL_BEGIN dispatch_semaphore_wait(registered, DISPATCH_TIME_FOREVER); [listenerRegistration remove]; - completion(snapshot, nil); + if (snapshot.metadata.fromCache && source == FIRFirestoreSourceServer) { + completion(nil, + [NSError errorWithDomain:FIRFirestoreErrorDomain + code:FIRFirestoreErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : + @"Failed to get documents from server. (However, these " + @"documents may exist in the local cache. Run again " + @"without setting source to FIRFirestoreSourceServer to " + @"retrieve the cached documents.)" + }]); + } else { + completion(snapshot, nil); + } }; - listenerRegistration = [self addSnapshotListenerInternalWithOptions:options listener:listener]; + listenerRegistration = + [self addSnapshotListenerInternalWithOptions:listenOptions listener:listener]; dispatch_semaphore_signal(registered); } -- cgit v1.2.3