FSTDatastore.mm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "Firestore/Source/Remote/FSTDatastore.h"
  17. #include <map>
  18. #include <memory>
  19. #include <vector>
  20. #import "FIRFirestoreErrors.h"
  21. #import "Firestore/Source/API/FIRFirestore+Internal.h"
  22. #import "Firestore/Source/API/FIRFirestoreVersion.h"
  23. #import "Firestore/Source/Local/FSTLocalStore.h"
  24. #import "Firestore/Source/Model/FSTDocument.h"
  25. #import "Firestore/Source/Model/FSTMutation.h"
  26. #import "Firestore/Source/Remote/FSTSerializerBeta.h"
  27. #import "Firestore/Source/Remote/FSTStream.h"
  28. #import "Firestore/Source/Util/FSTDispatchQueue.h"
  29. #include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h"
  30. #include "Firestore/core/src/firebase/firestore/auth/token.h"
  31. #include "Firestore/core/src/firebase/firestore/core/database_info.h"
  32. #include "Firestore/core/src/firebase/firestore/model/database_id.h"
  33. #include "Firestore/core/src/firebase/firestore/model/document_key.h"
  34. #include "Firestore/core/src/firebase/firestore/util/error_apple.h"
  35. #include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
  36. #include "Firestore/core/src/firebase/firestore/util/log.h"
  37. #include "Firestore/core/src/firebase/firestore/util/string_apple.h"
  38. #include "absl/memory/memory.h"
  39. #include "grpcpp/support/status_code_enum.h"
  40. namespace util = firebase::firestore::util;
  41. using firebase::firestore::auth::CredentialsProvider;
  42. using firebase::firestore::auth::Token;
  43. using firebase::firestore::core::DatabaseInfo;
  44. using firebase::firestore::model::DocumentKey;
  45. using firebase::firestore::model::DatabaseId;
  46. using firebase::firestore::remote::Datastore;
  47. using firebase::firestore::remote::GrpcConnection;
  48. using firebase::firestore::remote::WatchStream;
  49. using firebase::firestore::remote::WriteStream;
  50. NS_ASSUME_NONNULL_BEGIN
  51. // TODO(varconst): this is the only leftover from the dependency on gRPC
  52. // Objective-C client (where this constant is declared in `GRPCCall.h`). Remove
  53. // this once error handling is fully translated to C++.
  54. NSString *const kGRPCErrorDomain = @"io.grpc";
  55. #pragma mark - FSTDatastore
  56. @interface FSTDatastore ()
  57. @property(nonatomic, strong, readonly) FSTDispatchQueue *workerDispatchQueue;
  58. /**
  59. * An object for getting an auth token before each request. Does not own the CredentialsProvider
  60. * instance.
  61. */
  62. @property(nonatomic, assign, readonly) CredentialsProvider *credentials;
  63. @property(nonatomic, strong, readonly) FSTSerializerBeta *serializer;
  64. @end
  65. @implementation FSTDatastore {
  66. std::shared_ptr<Datastore> _datastore;
  67. }
  68. + (instancetype)datastoreWithDatabase:(const DatabaseInfo *)databaseInfo
  69. workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue
  70. credentials:(CredentialsProvider *)credentials {
  71. return [[FSTDatastore alloc] initWithDatabaseInfo:databaseInfo
  72. workerDispatchQueue:workerDispatchQueue
  73. credentials:credentials];
  74. }
  75. - (instancetype)initWithDatabaseInfo:(const DatabaseInfo *)databaseInfo
  76. workerDispatchQueue:(FSTDispatchQueue *)workerDispatchQueue
  77. credentials:(CredentialsProvider *)credentials {
  78. if (self = [super init]) {
  79. _databaseInfo = databaseInfo;
  80. _workerDispatchQueue = workerDispatchQueue;
  81. _credentials = credentials;
  82. _serializer = [[FSTSerializerBeta alloc] initWithDatabaseID:&databaseInfo->database_id()];
  83. _datastore = std::make_shared<Datastore>(*_databaseInfo, [_workerDispatchQueue implementation],
  84. _credentials, _serializer);
  85. _datastore->Start();
  86. if (!databaseInfo->ssl_enabled()) {
  87. GrpcConnection::UseInsecureChannel(databaseInfo->host());
  88. }
  89. }
  90. return self;
  91. }
  92. - (void)shutdown {
  93. _datastore->Shutdown();
  94. }
  95. - (NSString *)description {
  96. return [NSString stringWithFormat:@"<FSTDatastore: <DatabaseInfo: database_id:%s host:%s>>",
  97. self.databaseInfo->database_id().database_id().c_str(),
  98. self.databaseInfo->host().c_str()];
  99. }
  100. /**
  101. * Converts the error to an error within the domain FIRFirestoreErrorDomain.
  102. */
  103. + (NSError *)firestoreErrorForError:(NSError *)error {
  104. if (!error) {
  105. return error;
  106. } else if ([error.domain isEqualToString:FIRFirestoreErrorDomain]) {
  107. return error;
  108. } else if ([error.domain isEqualToString:kGRPCErrorDomain]) {
  109. HARD_ASSERT(error.code >= grpc::CANCELLED && error.code <= grpc::UNAUTHENTICATED,
  110. "Unknown GRPC error code: %s", error.code);
  111. return
  112. [NSError errorWithDomain:FIRFirestoreErrorDomain code:error.code userInfo:error.userInfo];
  113. } else {
  114. return [NSError errorWithDomain:FIRFirestoreErrorDomain
  115. code:FIRFirestoreErrorCodeUnknown
  116. userInfo:@{NSUnderlyingErrorKey : error}];
  117. }
  118. }
  119. + (BOOL)isAbortedError:(NSError *)error {
  120. HARD_ASSERT([error.domain isEqualToString:FIRFirestoreErrorDomain],
  121. "isAbortedError: only works with errors emitted by FSTDatastore.");
  122. return error.code == FIRFirestoreErrorCodeAborted;
  123. }
  124. + (BOOL)isPermanentWriteError:(NSError *)error {
  125. HARD_ASSERT([error.domain isEqualToString:FIRFirestoreErrorDomain],
  126. "isPerminanteWriteError: only works with errors emitted by FSTDatastore.");
  127. switch (error.code) {
  128. case FIRFirestoreErrorCodeCancelled:
  129. case FIRFirestoreErrorCodeUnknown:
  130. case FIRFirestoreErrorCodeDeadlineExceeded:
  131. case FIRFirestoreErrorCodeResourceExhausted:
  132. case FIRFirestoreErrorCodeInternal:
  133. case FIRFirestoreErrorCodeUnavailable:
  134. // Unauthenticated means something went wrong with our token and we need to retry with new
  135. // credentials which will happen automatically.
  136. case FIRFirestoreErrorCodeUnauthenticated:
  137. return NO;
  138. case FIRFirestoreErrorCodeInvalidArgument:
  139. case FIRFirestoreErrorCodeNotFound:
  140. case FIRFirestoreErrorCodeAlreadyExists:
  141. case FIRFirestoreErrorCodePermissionDenied:
  142. case FIRFirestoreErrorCodeFailedPrecondition:
  143. case FIRFirestoreErrorCodeAborted:
  144. // Aborted might be retried in some scenarios, but that is dependant on
  145. // the context and should handled individually by the calling code.
  146. // See https://cloud.google.com/apis/design/errors
  147. case FIRFirestoreErrorCodeOutOfRange:
  148. case FIRFirestoreErrorCodeUnimplemented:
  149. case FIRFirestoreErrorCodeDataLoss:
  150. return YES;
  151. default:
  152. return YES;
  153. }
  154. }
  155. - (void)commitMutations:(NSArray<FSTMutation *> *)mutations
  156. completion:(FSTVoidErrorBlock)completion {
  157. _datastore->CommitMutations(mutations, completion);
  158. }
  159. - (void)lookupDocuments:(const std::vector<DocumentKey> &)keys
  160. completion:(FSTVoidMaybeDocumentArrayErrorBlock)completion {
  161. _datastore->LookupDocuments(keys, completion);
  162. }
  163. - (std::shared_ptr<WatchStream>)createWatchStreamWithDelegate:(id)delegate {
  164. return _datastore->CreateWatchStream(delegate);
  165. }
  166. - (std::shared_ptr<WriteStream>)createWriteStreamWithDelegate:(id)delegate {
  167. return _datastore->CreateWriteStream(delegate);
  168. }
  169. @end
  170. NS_ASSUME_NONNULL_END