Google Cloud Bigtable C++ Client  1.40.2
A C++ Client Library for Google Cloud Bigtable
rpc_retry_policy.h
Go to the documentation of this file.
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_RPC_RETRY_POLICY_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_RPC_RETRY_POLICY_H
17 
18 #include "google/cloud/bigtable/internal/rpc_policy_parameters.h"
19 #include "google/cloud/bigtable/version.h"
20 #include "google/cloud/grpc_error_delegate.h"
21 #include "google/cloud/internal/retry_policy.h"
22 #include "google/cloud/status.h"
23 #include "absl/memory/memory.h"
24 #include <grpcpp/grpcpp.h>
25 #include <memory>
26 
27 namespace google {
28 namespace cloud {
29 namespace bigtable_internal {
31 
32 template <typename T>
33 class CommonRetryPolicy;
34 
36 } // namespace bigtable_internal
37 namespace bigtable {
39 namespace internal {
40 /// An adapter to use `grpc::Status` with the `google::cloud::*Policies`.
41 struct SafeGrpcRetry {
42  static inline bool IsOk(Status const& status) { return status.ok(); }
43  static inline bool IsTransientFailure(Status const& status) {
44  auto const code = status.code();
45  return code == StatusCode::kAborted || code == StatusCode::kUnavailable ||
46  google::cloud::internal::IsTransientInternalError(status);
47  }
48  static inline bool IsPermanentFailure(Status const& status) {
49  return !IsOk(status) && !IsTransientFailure(status);
50  }
51 
52  // TODO(#2344) - remove ::grpc::Status version.
53  static inline bool IsOk(grpc::Status const& status) { return status.ok(); }
54  static inline bool IsTransientFailure(grpc::Status const& status) {
55  return IsTransientFailure(MakeStatusFromRpcError(status));
56  }
57  static inline bool IsPermanentFailure(grpc::Status const& status) {
58  return !IsOk(status) && !IsTransientFailure(status);
59  }
60 };
61 } // namespace internal
62 
63 /**
64  * Define the interface for controlling how the Bigtable client
65  * retries RPC operations.
66  *
67  * The C++ client for Bigtable needs to hide partial and temporary
68  * failures from the application. However, we need to give the users
69  * enough flexibility to control how many attempts are made to reissue
70  * operations, how often these attempts are executed, and how to
71  * signal that an error has occurred.
72  *
73  * The application provides an instance of this class when the Table
74  * (or TableAdmin) object is created. This instance serves as a
75  * prototype to create new RPCRetryPolicy objects of the same
76  * (dynamic) type and with the same initial state.
77  *
78  */
80  public:
81  using RetryableTraits = internal::SafeGrpcRetry;
82 
83  virtual ~RPCRetryPolicy() = default;
84 
85  /**
86  * Return a new copy of this object.
87  *
88  * Typically implemented as
89  * @code
90  * return std::unique_ptr<RPCRetryPolicy>(new Foo(*this));
91  * @endcode
92  */
93  virtual std::unique_ptr<RPCRetryPolicy> clone() const = 0;
94 
95  /**
96  * Update the ClientContext for the next call.
97  */
98  virtual void Setup(grpc::ClientContext& context) const = 0;
99 
100  /**
101  * Handle an RPC failure.
102  *
103  * @return true if the RPC operation should be retried.
104  */
105  virtual bool OnFailure(Status const& status) = 0;
106  // TODO(#2344) - remove ::grpc::Status version.
107  virtual bool OnFailure(grpc::Status const& status) = 0;
108 
109  static bool IsPermanentFailure(Status const& status) {
110  return internal::SafeGrpcRetry::IsPermanentFailure(status);
111  }
112  // TODO(#2344) - remove ::grpc::Status version.
113  static bool IsPermanentFailure(grpc::Status const& status) {
114  return internal::SafeGrpcRetry::IsPermanentFailure(status);
115  }
116 
117  virtual bool IsExhausted() const { return exhausted_; }
118 
119  private:
120  template <typename T>
121  friend class bigtable_internal::CommonRetryPolicy;
122 
123  bool exhausted_ = false;
124 };
125 
126 /// Return an instance of the default RPCRetryPolicy.
128  internal::RPCPolicyParameters defaults);
129 
130 /**
131  * Implement a simple "count errors and then stop" retry policy.
132  */
134  public:
135  explicit LimitedErrorCountRetryPolicy(int maximum_failures)
136  : impl_(maximum_failures) {}
137 
138  std::unique_ptr<RPCRetryPolicy> clone() const override;
139  void Setup(grpc::ClientContext& context) const override;
140  bool OnFailure(Status const& status) override;
141  // TODO(#2344) - remove ::grpc::Status version.
142  bool OnFailure(grpc::Status const& status) override;
143  bool IsExhausted() const override;
144 
145  private:
146  using Impl = ::google::cloud::internal::LimitedErrorCountRetryPolicy<
147  internal::SafeGrpcRetry>;
148  Impl impl_;
149 };
150 
151 /**
152  * Implement a simple "keep trying for this time" retry policy.
153  */
155  public:
156  explicit LimitedTimeRetryPolicy(internal::RPCPolicyParameters defaults);
157  template <typename DurationT>
158  explicit LimitedTimeRetryPolicy(DurationT maximum_duration)
159  : impl_(maximum_duration) {}
160 
161  std::unique_ptr<RPCRetryPolicy> clone() const override;
162  void Setup(grpc::ClientContext& context) const override;
163  bool OnFailure(Status const& status) override;
164  // TODO(#2344) - remove ::grpc::Status version.
165  bool OnFailure(grpc::Status const& status) override;
166  bool IsExhausted() const override;
167 
168  private:
169  using Impl = ::google::cloud::internal::LimitedTimeRetryPolicy<
170  internal::SafeGrpcRetry>;
171  Impl impl_;
172 };
173 
175 } // namespace bigtable
176 namespace bigtable_internal {
178 
179 template <typename ReturnType>
180 class CommonRetryPolicy : public ReturnType {
181  public:
182  explicit CommonRetryPolicy(std::unique_ptr<bigtable::RPCRetryPolicy> impl)
183  : impl_(std::move(impl)) {}
184  ~CommonRetryPolicy() override = default;
185 
186  std::unique_ptr<ReturnType> clone() const override {
187  return absl::make_unique<CommonRetryPolicy>(impl_->clone());
188  }
189  bool OnFailure(Status const& s) override {
190  auto retry = impl_->OnFailure(s);
191  if (!retry && !IsPermanentFailure(s)) impl_->exhausted_ = true;
192  return retry;
193  }
194  bool IsExhausted() const override { return impl_->IsExhausted(); }
195  bool IsPermanentFailure(Status const& s) const override {
197  }
198  void OnFailureImpl() override {}
199 
200  private:
201  std::unique_ptr<bigtable::RPCRetryPolicy> impl_;
202 };
203 
204 template <typename ReturnType>
205 std::unique_ptr<ReturnType> MakeCommonRetryPolicy(
206  std::unique_ptr<bigtable::RPCRetryPolicy> policy) {
207  return absl::make_unique<CommonRetryPolicy<ReturnType>>(std::move(policy));
208 }
209 
211 } // namespace bigtable_internal
212 } // namespace cloud
213 } // namespace google
214 
215 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_RPC_RETRY_POLICY_H