30 #include "absl/memory/memory.h"
31 #include "absl/types/optional.h"
43 #define MAX_MAX_RETRY_ATTEMPTS 5
54 builder->service_config_parser()->RegisterParser(
55 absl::make_unique<RetryServiceConfigParser>());
65 "field:retryThrottling error:Type should be object");
67 std::vector<grpc_error_handle> error_list;
72 "field:retryThrottling field:maxTokens error:Not found"));
75 "field:retryThrottling field:maxTokens error:Type should be "
80 if (*max_milli_tokens <= 0) {
82 "field:retryThrottling field:maxTokens error:should be "
83 "greater than zero"));
90 "field:retryThrottling field:tokenRatio error:Not found"));
93 "field:retryThrottling field:tokenRatio error:type should be "
97 size_t whole_len =
it->second.string_value().size();
98 const char*
value =
it->second.string_value().c_str();
101 const char* decimal_point = strchr(
value,
'.');
102 if (decimal_point !=
nullptr) {
103 whole_len =
static_cast<size_t>(decimal_point -
value);
105 size_t decimal_len = strlen(decimal_point + 1);
106 if (decimal_len > 3) decimal_len = 3;
110 "field:retryThrottling field:tokenRatio error:Failed "
115 for (
size_t i = 0;
i < (3 - decimal_len); ++
i) {
116 decimal_multiplier *= 10;
118 decimal_value *= decimal_multiplier;
123 "field:retryThrottling field:tokenRatio error:Failed "
128 static_cast<int>((whole_value * multiplier) + decimal_value);
129 if (*milli_token_ratio <= 0) {
131 "field:retryThrottling field:tokenRatio error:value should "
132 "be greater than 0"));
140 std::unique_ptr<ServiceConfigParser::ParsedConfig>
150 ParseRetryThrottling(
it->second, &max_milli_tokens, &milli_token_ratio);
152 return absl::make_unique<RetryGlobalConfig>(max_milli_tokens,
160 Duration* initial_backoff,
Duration* max_backoff,
float* backoff_multiplier,
165 "field:retryPolicy error:should be of type object");
167 std::vector<grpc_error_handle> error_list;
172 "field:maxAttempts error:required field missing"));
176 "field:maxAttempts error:should be of type number"));
180 if (*max_attempts <= 1) {
182 "field:maxAttempts error:should be at least 2"));
185 "service config: clamped retryPolicy.maxAttempts at %d",
193 initial_backoff, &error_list) &&
196 "field:initialBackoff error:must be greater than 0"));
200 max_backoff, &error_list) &&
203 "field:maxBackoff error:must be greater than 0"));
209 "field:backoffMultiplier error:required field missing"));
213 "field:backoffMultiplier error:should be of type number"));
215 if (sscanf(
it->second.string_value().c_str(),
"%f", backoff_multiplier) !=
218 "field:backoffMultiplier error:failed to parse"));
219 }
else if (*backoff_multiplier <= 0) {
221 "field:backoffMultiplier error:must be greater than 0"));
230 "field:retryableStatusCodes error:must be of type array"));
235 "field:retryableStatusCodes error:status codes should be of type "
243 "field:retryableStatusCodes error:failed to parse status code"));
255 Duration per_attempt_recv_timeout_value;
258 "field:perAttemptRecvTimeout error:type must be STRING of the "
259 "form given by google.proto.Duration."));
261 *per_attempt_recv_timeout = per_attempt_recv_timeout_value;
266 "field:perAttemptRecvTimeout error:must be greater than 0"));
269 }
else if (retryable_status_codes->
Empty()) {
273 "field:retryableStatusCodes error:must be non-empty if "
274 "perAttemptRecvTimeout not present"));
279 if (retryable_status_codes->
Empty()) {
281 "field:retryableStatusCodes error:must be non-empty"));
289 std::unique_ptr<ServiceConfigParser::ParsedConfig>
297 int max_attempts = 0;
300 float backoff_multiplier = 0;
303 *
error = ParseRetryPolicy(
args,
it->second, &max_attempts, &initial_backoff,
304 &max_backoff, &backoff_multiplier,
305 &retryable_status_codes, &per_attempt_recv_timeout);
307 return absl::make_unique<RetryMethodConfig>(
308 max_attempts, initial_backoff, max_backoff, backoff_multiplier,
309 retryable_status_codes, per_attempt_recv_timeout);