Skip to content

Commit

Permalink
Make address resolution error use the default service config (#11577)
Browse files Browse the repository at this point in the history
Fixes #11040.
  • Loading branch information
kannanjgithub authored Oct 1, 2024
1 parent 50e442f commit fa26a8b
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
10 changes: 9 additions & 1 deletion core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,15 @@ void updateConfigSelector(@Nullable InternalConfigSelector config) {
// Must run in SynchronizationContext.
void onConfigError() {
if (configSelector.get() == INITIAL_PENDING_SELECTOR) {
updateConfigSelector(null);
// Apply Default Service Config if initial name resolution fails.
if (defaultServiceConfig != null) {
updateConfigSelector(defaultServiceConfig.getDefaultConfigSelector());
lastServiceConfig = defaultServiceConfig;
channelLogger.log(ChannelLogLevel.ERROR,
"Initial Name Resolution error, using default service config");
} else {
updateConfigSelector(null);
}
}
}

Expand Down
53 changes: 52 additions & 1 deletion core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import io.grpc.InternalChannelz;
import io.grpc.InternalChannelz.ChannelStats;
import io.grpc.InternalChannelz.ChannelTrace;
import io.grpc.InternalChannelz.ChannelTrace.Event.Severity;
import io.grpc.InternalConfigSelector;
import io.grpc.InternalInstrumented;
import io.grpc.LoadBalancer;
Expand Down Expand Up @@ -123,6 +124,7 @@
import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
import io.grpc.internal.ManagedChannelImplBuilder.FixedPortProvider;
import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
import io.grpc.internal.ManagedChannelServiceConfig.MethodInfo;
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
import io.grpc.internal.TestUtils.MockClientTransportInfo;
import io.grpc.stub.ClientCalls;
Expand Down Expand Up @@ -1127,6 +1129,55 @@ public void noMoreCallbackAfterLoadBalancerShutdown_configError() throws Interru
verifyNoMoreInteractions(mockLoadBalancer);
}

@Test
public void addressResolutionError_noPriorNameResolution_usesDefaultServiceConfig()
throws Exception {
Map<String, Object> rawServiceConfig =
parseConfig("{\"methodConfig\":[{"
+ "\"name\":[{\"service\":\"service\"}],"
+ "\"waitForReady\":true}]}");
ManagedChannelServiceConfig managedChannelServiceConfig =
createManagedChannelServiceConfig(rawServiceConfig, null);
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri)
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
.setResolvedAtStart(false)
.build();
nameResolverFactory.nextConfigOrError.set(
ConfigOrError.fromConfig(managedChannelServiceConfig));
channelBuilder.nameResolverFactory(nameResolverFactory);
Map<String, Object> defaultServiceConfig =
parseConfig("{\"methodConfig\":[{"
+ "\"name\":[{\"service\":\"service\"}],"
+ "\"waitForReady\":true}]}");
channelBuilder.defaultServiceConfig(defaultServiceConfig);
Status resolutionError = Status.UNAVAILABLE.withDescription("Resolution failed");
channelBuilder.maxTraceEvents(10);
createChannel();
FakeNameResolverFactory.FakeNameResolver resolver = nameResolverFactory.resolvers.get(0);

resolver.listener.onError(resolutionError);

InternalConfigSelector configSelector = channel.getConfigSelector();
ManagedChannelServiceConfig config =
(ManagedChannelServiceConfig) configSelector.selectConfig(null).getConfig();
MethodInfo methodConfig = config.getMethodConfig(method);
assertThat(methodConfig.waitForReady).isTrue();
timer.forwardNanos(1234);
assertThat(getStats(channel).channelTrace.events).contains(new ChannelTrace.Event.Builder()
.setDescription("Initial Name Resolution error, using default service config")
.setSeverity(Severity.CT_ERROR)
.setTimestampNanos(0)
.build());

// Check that "lastServiceConfig" variable has been set above: a config resolution with the same
// config simply gets ignored and not gets reassigned.
resolver.resolved();
timer.forwardNanos(1234);
assertThat(getStats(channel).channelTrace.events.stream().filter(
event -> event.description.equals("Service config changed")).count()).isEqualTo(0);
}

@Test
public void interceptor() throws Exception {
final AtomicLong atomic = new AtomicLong();
Expand Down Expand Up @@ -4595,7 +4646,7 @@ public void notUseDefaultImmediatelyIfEnableLookUp() throws Exception {
int size = getStats(channel).channelTrace.events.size();
assertThat(getStats(channel).channelTrace.events.get(size - 1))
.isNotEqualTo(new ChannelTrace.Event.Builder()
.setDescription("Using default service config")
.setDescription("timer.forwardNanos(1234);")
.setSeverity(ChannelTrace.Event.Severity.CT_INFO)
.setTimestampNanos(timer.getTicker().read())
.build());
Expand Down

0 comments on commit fa26a8b

Please sign in to comment.