1 // Copyright 2018 Google LLC 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 // http://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_POLLING_POLICY_H 16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_POLLING_POLICY_H 17 18 #include "google/cloud/bigtable/rpc_backoff_policy.h" 19 #include "google/cloud/bigtable/rpc_retry_policy.h" 20 #include "google/cloud/bigtable/version.h" 21 #include "google/cloud/grpc_error_delegate.h" 22 #include <grpcpp/grpcpp.h> 23 24 namespace google { 25 namespace cloud { 26 namespace bigtable { 27 inline namespace BIGTABLE_CLIENT_NS { 28 /** 29 * Define the interface for providing asynchronous repetitive call rules 30 * 31 */ 32 class PollingPolicy { 33 public: 34 virtual ~PollingPolicy() = default; 35 36 /** 37 * Return a new copy of this object. 38 * 39 * Typically implemented as 40 * @code 41 * return std::unique_ptr<PollingPolicy>(new Foo(*this)); 42 * @endcode 43 */ 44 virtual std::unique_ptr<PollingPolicy> clone() const = 0; 45 46 virtual void Setup(grpc::ClientContext& context) = 0; 47 48 /** 49 * Return true if `status` represents a permanent error that cannot be 50 * retried. 51 * TODO(#2344): remove `grpc::Status` version. 52 */ IsPermanentError(grpc::Status const & status)53 virtual bool IsPermanentError(grpc::Status const& status) { 54 return IsPermanentError(MakeStatusFromRpcError(status)); 55 } 56 57 /** 58 * Return true if `status` represents a permanent error that cannot be 59 * retried. 60 */ 61 virtual bool IsPermanentError(google::cloud::Status const& status) = 0; 62 63 /** 64 * Handle an RPC failure. 65 * TODO(#2344): remove `grpc::Status` version. 66 * 67 * @return true if the RPC operation should be retried. 68 */ OnFailure(grpc::Status const & status)69 virtual bool OnFailure(grpc::Status const& status) { 70 return OnFailure(MakeStatusFromRpcError(status)); 71 } 72 73 /** 74 * Handle an RPC failure. 75 * 76 * @return true if the RPC operation should be retried. 77 */ 78 virtual bool OnFailure(google::cloud::Status const& status) = 0; 79 80 /** 81 * Return true if we cannot try again. 82 */ 83 virtual bool Exhausted() = 0; 84 85 /** 86 * Return for how long we should wait before trying again. 87 */ 88 virtual std::chrono::milliseconds WaitPeriod() = 0; 89 }; 90 91 /** 92 * Construct a polling policy from existing Retry and Backoff policies. 93 * 94 * A polling policy can be built by composing a retry and backoff policy. For 95 * example, to create a polling policy that "retries N times, waiting a fixed 96 * period between retries" you could compose the "try N times" retry policy with 97 * the "wait a fixed period between retries". 98 * 99 * This class makes it easier to create such composed polling policies. 100 * 101 * @tparam Retry the RPC retry strategy used to limit the number or the total 102 * duration of the polling strategy. 103 * @tparam Backoff the RPC backoff strategy used to control how often the 104 * library polls. 105 */ 106 template <typename Retry = LimitedTimeRetryPolicy, 107 typename Backoff = ExponentialBackoffPolicy> 108 class GenericPollingPolicy : public PollingPolicy { 109 public: GenericPollingPolicy(internal::RPCPolicyParameters defaults)110 explicit GenericPollingPolicy(internal::RPCPolicyParameters defaults) 111 : rpc_retry_policy_(Retry(defaults)), 112 rpc_backoff_policy_(Backoff(defaults)) {} GenericPollingPolicy(Retry retry,Backoff backoff)113 GenericPollingPolicy(Retry retry, Backoff backoff) 114 : rpc_retry_policy_(std::move(retry)), 115 rpc_backoff_policy_(std::move(backoff)) {} 116 clone()117 std::unique_ptr<PollingPolicy> clone() const override { 118 return std::unique_ptr<PollingPolicy>(new GenericPollingPolicy(*this)); 119 } 120 Setup(grpc::ClientContext & context)121 void Setup(grpc::ClientContext& context) override { 122 rpc_retry_policy_.Setup(context); 123 rpc_backoff_policy_.Setup(context); 124 } 125 IsPermanentError(google::cloud::Status const & status)126 bool IsPermanentError(google::cloud::Status const& status) override { 127 return RPCRetryPolicy::IsPermanentFailure(status); 128 } 129 OnFailure(google::cloud::Status const & status)130 bool OnFailure(google::cloud::Status const& status) override { 131 return rpc_retry_policy_.OnFailure(status); 132 } 133 Exhausted()134 bool Exhausted() override { return !OnFailure(google::cloud::Status()); } 135 WaitPeriod()136 std::chrono::milliseconds WaitPeriod() override { 137 return rpc_backoff_policy_.OnCompletion(grpc::Status::OK); 138 } 139 140 private: 141 Retry rpc_retry_policy_; 142 Backoff rpc_backoff_policy_; 143 }; 144 145 std::unique_ptr<PollingPolicy> DefaultPollingPolicy( 146 internal::RPCPolicyParameters defaults); 147 148 } // namespace BIGTABLE_CLIENT_NS 149 } // namespace bigtable 150 } // namespace cloud 151 } // namespace google 152 153 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_POLLING_POLICY_H 154