Skip to content

Commit fa26a8b

Browse files
Make address resolution error use the default service config (#11577)
Fixes #11040.
1 parent 50e442f commit fa26a8b

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

core/src/main/java/io/grpc/internal/ManagedChannelImpl.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,15 @@ void updateConfigSelector(@Nullable InternalConfigSelector config) {
956956
// Must run in SynchronizationContext.
957957
void onConfigError() {
958958
if (configSelector.get() == INITIAL_PENDING_SELECTOR) {
959-
updateConfigSelector(null);
959+
// Apply Default Service Config if initial name resolution fails.
960+
if (defaultServiceConfig != null) {
961+
updateConfigSelector(defaultServiceConfig.getDefaultConfigSelector());
962+
lastServiceConfig = defaultServiceConfig;
963+
channelLogger.log(ChannelLogLevel.ERROR,
964+
"Initial Name Resolution error, using default service config");
965+
} else {
966+
updateConfigSelector(null);
967+
}
960968
}
961969
}
962970

core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java

+52-1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import io.grpc.InternalChannelz;
8585
import io.grpc.InternalChannelz.ChannelStats;
8686
import io.grpc.InternalChannelz.ChannelTrace;
87+
import io.grpc.InternalChannelz.ChannelTrace.Event.Severity;
8788
import io.grpc.InternalConfigSelector;
8889
import io.grpc.InternalInstrumented;
8990
import io.grpc.LoadBalancer;
@@ -123,6 +124,7 @@
123124
import io.grpc.internal.ManagedChannelImplBuilder.ClientTransportFactoryBuilder;
124125
import io.grpc.internal.ManagedChannelImplBuilder.FixedPortProvider;
125126
import io.grpc.internal.ManagedChannelImplBuilder.UnsupportedClientTransportFactoryBuilder;
127+
import io.grpc.internal.ManagedChannelServiceConfig.MethodInfo;
126128
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
127129
import io.grpc.internal.TestUtils.MockClientTransportInfo;
128130
import io.grpc.stub.ClientCalls;
@@ -1127,6 +1129,55 @@ public void noMoreCallbackAfterLoadBalancerShutdown_configError() throws Interru
11271129
verifyNoMoreInteractions(mockLoadBalancer);
11281130
}
11291131

1132+
@Test
1133+
public void addressResolutionError_noPriorNameResolution_usesDefaultServiceConfig()
1134+
throws Exception {
1135+
Map<String, Object> rawServiceConfig =
1136+
parseConfig("{\"methodConfig\":[{"
1137+
+ "\"name\":[{\"service\":\"service\"}],"
1138+
+ "\"waitForReady\":true}]}");
1139+
ManagedChannelServiceConfig managedChannelServiceConfig =
1140+
createManagedChannelServiceConfig(rawServiceConfig, null);
1141+
FakeNameResolverFactory nameResolverFactory =
1142+
new FakeNameResolverFactory.Builder(expectedUri)
1143+
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
1144+
.setResolvedAtStart(false)
1145+
.build();
1146+
nameResolverFactory.nextConfigOrError.set(
1147+
ConfigOrError.fromConfig(managedChannelServiceConfig));
1148+
channelBuilder.nameResolverFactory(nameResolverFactory);
1149+
Map<String, Object> defaultServiceConfig =
1150+
parseConfig("{\"methodConfig\":[{"
1151+
+ "\"name\":[{\"service\":\"service\"}],"
1152+
+ "\"waitForReady\":true}]}");
1153+
channelBuilder.defaultServiceConfig(defaultServiceConfig);
1154+
Status resolutionError = Status.UNAVAILABLE.withDescription("Resolution failed");
1155+
channelBuilder.maxTraceEvents(10);
1156+
createChannel();
1157+
FakeNameResolverFactory.FakeNameResolver resolver = nameResolverFactory.resolvers.get(0);
1158+
1159+
resolver.listener.onError(resolutionError);
1160+
1161+
InternalConfigSelector configSelector = channel.getConfigSelector();
1162+
ManagedChannelServiceConfig config =
1163+
(ManagedChannelServiceConfig) configSelector.selectConfig(null).getConfig();
1164+
MethodInfo methodConfig = config.getMethodConfig(method);
1165+
assertThat(methodConfig.waitForReady).isTrue();
1166+
timer.forwardNanos(1234);
1167+
assertThat(getStats(channel).channelTrace.events).contains(new ChannelTrace.Event.Builder()
1168+
.setDescription("Initial Name Resolution error, using default service config")
1169+
.setSeverity(Severity.CT_ERROR)
1170+
.setTimestampNanos(0)
1171+
.build());
1172+
1173+
// Check that "lastServiceConfig" variable has been set above: a config resolution with the same
1174+
// config simply gets ignored and not gets reassigned.
1175+
resolver.resolved();
1176+
timer.forwardNanos(1234);
1177+
assertThat(getStats(channel).channelTrace.events.stream().filter(
1178+
event -> event.description.equals("Service config changed")).count()).isEqualTo(0);
1179+
}
1180+
11301181
@Test
11311182
public void interceptor() throws Exception {
11321183
final AtomicLong atomic = new AtomicLong();
@@ -4595,7 +4646,7 @@ public void notUseDefaultImmediatelyIfEnableLookUp() throws Exception {
45954646
int size = getStats(channel).channelTrace.events.size();
45964647
assertThat(getStats(channel).channelTrace.events.get(size - 1))
45974648
.isNotEqualTo(new ChannelTrace.Event.Builder()
4598-
.setDescription("Using default service config")
4649+
.setDescription("timer.forwardNanos(1234);")
45994650
.setSeverity(ChannelTrace.Event.Severity.CT_INFO)
46004651
.setTimestampNanos(timer.getTicker().read())
46014652
.build());

0 commit comments

Comments
 (0)