Google Cloud Spanner C++ Client  1.32.1
A C++ Client Library for Google Cloud Spanner
retry_policy.h
Go to the documentation of this file.
1 // Copyright 2019 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_SPANNER_RETRY_POLICY_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_RETRY_POLICY_H
17 
18 #include "google/cloud/spanner/internal/status_utils.h"
19 #include "google/cloud/spanner/version.h"
20 #include "google/cloud/internal/retry_policy.h"
21 #include "google/cloud/status.h"
22 #include "absl/strings/match.h"
23 
24 namespace google {
25 namespace cloud {
26 namespace spanner_internal {
27 inline namespace SPANNER_CLIENT_NS {
28 
29 /// Define the gRPC status code semantics for retrying requests.
30 struct SafeGrpcRetry {
31  static inline bool IsOk(google::cloud::Status const& status) {
32  return status.ok();
33  }
34  static inline bool IsTransientFailure(google::cloud::Status const& status) {
35  if (status.code() == StatusCode::kUnavailable ||
37  return true;
38  }
39  // Treat the unexpected termination of the gRPC connection as retryable.
40  // There is no explicit indication of this, but it will result in an
41  // INTERNAL status with one of the `kTransientFailureMessages`.
42  if (status.code() == StatusCode::kInternal) {
43  constexpr char const* kTransientFailureMessages[] = {
44  "Received unexpected EOS on DATA frame from server",
45  "Connection closed with unknown cause",
46  "HTTP/2 error code: INTERNAL_ERROR", "RST_STREAM"};
47  for (auto const& message : kTransientFailureMessages) {
48  if (absl::StrContains(status.message(), message)) return true;
49  }
50  }
51  return false;
52  }
53  static inline bool IsPermanentFailure(google::cloud::Status const& status) {
54  return !IsOk(status) && !IsTransientFailure(status);
55  }
56 };
57 
58 /// Define the gRPC status code semantics for rerunning transactions.
59 struct SafeTransactionRerun {
60  static inline bool IsOk(google::cloud::Status const& status) {
61  return status.ok();
62  }
63  static inline bool IsTransientFailure(google::cloud::Status const& status) {
64  return status.code() == StatusCode::kAborted || IsSessionNotFound(status);
65  }
66  static inline bool IsPermanentFailure(google::cloud::Status const& status) {
67  return !IsOk(status) && !IsTransientFailure(status);
68  }
69 };
70 } // namespace SPANNER_CLIENT_NS
71 } // namespace spanner_internal
72 
73 namespace spanner {
74 inline namespace SPANNER_CLIENT_NS {
75 
76 /// The base class for retry policies.
77 using RetryPolicy = ::google::cloud::internal::TraitBasedRetryPolicy<
78  spanner_internal::SafeGrpcRetry>;
79 
80 /// A retry policy that limits based on time.
81 using LimitedTimeRetryPolicy =
82  ::google::cloud::internal::LimitedTimeRetryPolicy<
83  spanner_internal::SafeGrpcRetry>;
84 
85 /// A retry policy that limits the number of times a request can fail.
86 using LimitedErrorCountRetryPolicy =
87  google::cloud::internal::LimitedErrorCountRetryPolicy<
88  spanner_internal::SafeGrpcRetry>;
89 
90 /// The base class for transaction rerun policies.
91 using TransactionRerunPolicy = ::google::cloud::internal::TraitBasedRetryPolicy<
92  spanner_internal::SafeTransactionRerun>;
93 
94 /// A transaction rerun policy that limits the duration of the rerun loop.
95 using LimitedTimeTransactionRerunPolicy =
96  google::cloud::internal::LimitedTimeRetryPolicy<
97  spanner_internal::SafeTransactionRerun>;
98 
99 /// A transaction rerun policy that limits the number of failures.
100 using LimitedErrorCountTransactionRerunPolicy =
101  google::cloud::internal::LimitedErrorCountRetryPolicy<
102  spanner_internal::SafeTransactionRerun>;
103 
104 } // namespace SPANNER_CLIENT_NS
105 } // namespace spanner
106 } // namespace cloud
107 } // namespace google
108 
109 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_RETRY_POLICY_H