Skip to content

Commit

Permalink
xds: populate envoy RetryPolicy with no retryOn to resolver (#8511)
Browse files Browse the repository at this point in the history
Envoy RetryPolicy with empty retryOn should not be ignored as no retry config when selecting Route config. Therefore, if xDS update for a route contains a RetryPolicy that has no RetryOn value that we support, but the virtual host config does, xds client should choose the Envoy RetryPolicy from the route (even with no RetryOn), rather than choosing the one from virtual host, and try to convert it into grpc RetryPolicy, and end up with no retry.
  • Loading branch information
dapengzhang0 committed Sep 13, 2021
1 parent 17c2460 commit dbf9202
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 11 deletions.
11 changes: 4 additions & 7 deletions xds/src/main/java/io/grpc/xds/ClientXdsClient.java
Expand Up @@ -1281,13 +1281,10 @@ private static StructOrError<RetryPolicy> parseRetryPolicy(
retryableStatusCodesBuilder.add(code);
}
List<Code> retryableStatusCodes = retryableStatusCodesBuilder.build();
if (!retryableStatusCodes.isEmpty()) {
return StructOrError.fromStruct(
RetryPolicy.create(
maxAttempts, retryableStatusCodes, initialBackoff, maxBackoff,
/* perAttemptRecvTimeout= */ null));
}
return null;
return StructOrError.fromStruct(
RetryPolicy.create(
maxAttempts, retryableStatusCodes, initialBackoff, maxBackoff,
/* perAttemptRecvTimeout= */ null));
}

@VisibleForTesting
Expand Down
5 changes: 3 additions & 2 deletions xds/src/main/java/io/grpc/xds/XdsNameResolver.java
Expand Up @@ -182,13 +182,14 @@ public void shutdown() {
@VisibleForTesting
static Map<String, ?> generateServiceConfigWithMethodConfig(
@Nullable Long timeoutNano, @Nullable RetryPolicy retryPolicy) {
if (timeoutNano == null && retryPolicy == null) {
if (timeoutNano == null
&& (retryPolicy == null || retryPolicy.retryableStatusCodes().isEmpty())) {
return Collections.emptyMap();
}
ImmutableMap.Builder<String, Object> methodConfig = ImmutableMap.builder();
methodConfig.put(
"name", Collections.singletonList(Collections.emptyMap()));
if (retryPolicy != null) {
if (retryPolicy != null && !retryPolicy.retryableStatusCodes().isEmpty()) {
ImmutableMap.Builder<String, Object> rawRetryPolicy = ImmutableMap.builder();
rawRetryPolicy.put("maxAttempts", (double) retryPolicy.maxAttempts());
rawRetryPolicy.put("initialBackoff", Durations.toString(retryPolicy.initialBackoff()));
Expand Down
3 changes: 2 additions & 1 deletion xds/src/test/java/io/grpc/xds/ClientXdsClientDataTest.java
Expand Up @@ -552,7 +552,8 @@ public void parseRouteAction_withRetryPolicy() {
.setRetryPolicy(builder.build())
.build();
struct = ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
assertThat(struct.getStruct().retryPolicy()).isNull();
assertThat(struct.getStruct().retryPolicy()).isNotNull();
assertThat(struct.getStruct().retryPolicy().retryableStatusCodes()).isEmpty();

// base_interval unset
builder
Expand Down
14 changes: 13 additions & 1 deletion xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java
Expand Up @@ -988,6 +988,8 @@ public void generateServiceConfig_forPerMethodConfig() throws IOException {
RetryPolicy retryPolicy = RetryPolicy.create(
4, ImmutableList.of(Code.UNAVAILABLE, Code.CANCELLED), Durations.fromMillis(100),
Durations.fromMillis(200), null);
RetryPolicy retryPolicyWithEmptyStatusCodes = RetryPolicy.create(
4, ImmutableList.<Code>of(), Durations.fromMillis(100), Durations.fromMillis(200), null);

// timeout only
String expectedServiceConfigJson = "{\n"
Expand All @@ -1001,6 +1003,11 @@ public void generateServiceConfig_forPerMethodConfig() throws IOException {
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(timeoutNano, null))
.isEqualTo(expectedServiceConfig);

// timeout and retry with empty retriable status codes
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(
timeoutNano, retryPolicyWithEmptyStatusCodes))
.isEqualTo(expectedServiceConfig);

// retry only
expectedServiceConfigJson = "{\n"
+ " \"methodConfig\": [{\n"
Expand All @@ -1021,6 +1028,7 @@ public void generateServiceConfig_forPerMethodConfig() throws IOException {
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(null, retryPolicy))
.isEqualTo(expectedServiceConfig);


// timeout and retry
expectedServiceConfigJson = "{\n"
+ " \"methodConfig\": [{\n"
Expand All @@ -1043,12 +1051,16 @@ public void generateServiceConfig_forPerMethodConfig() throws IOException {
.isEqualTo(expectedServiceConfig);

// no timeout and no retry
// timeout and retry
expectedServiceConfigJson = "{}";
expectedServiceConfig =
(Map<String, ?>) JsonParser.parse(expectedServiceConfigJson);
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(null, null))
.isEqualTo(expectedServiceConfig);

// retry with emtry retriable status codes only
assertThat(XdsNameResolver.generateServiceConfigWithMethodConfig(
null, retryPolicyWithEmptyStatusCodes))
.isEqualTo(expectedServiceConfig);
}

@Test
Expand Down

0 comments on commit dbf9202

Please sign in to comment.