@@ -132,7 +132,7 @@ final class XdsNameResolver extends NameResolver {
132132 // NamedFilterConfig.filterStateKey -> filter_instance.
133133 private final HashMap <String , Filter > activeFilters = new HashMap <>();
134134
135- private volatile RoutingConfig routingConfig = RoutingConfig . EMPTY ;
135+ private volatile RoutingConfig routingConfig ;
136136 private Listener2 listener ;
137137 private ObjectPool <XdsClient > xdsClientPool ;
138138 private XdsClient xdsClient ;
@@ -306,7 +306,7 @@ private void updateResolutionResult() {
306306
307307 if (logger .isLoggable (XdsLogLevel .INFO )) {
308308 logger .log (
309- XdsLogLevel .INFO , "Generated service config:\n {0}" , new Gson ().toJson (rawServiceConfig ));
309+ XdsLogLevel .INFO , "Generated service config: {0}" , new Gson ().toJson (rawServiceConfig ));
310310 }
311311 ConfigOrError parsedServiceConfig = serviceConfigParser .parseServiceConfig (rawServiceConfig );
312312 Attributes attrs =
@@ -320,7 +320,7 @@ private void updateResolutionResult() {
320320 .setAttributes (attrs )
321321 .setServiceConfig (parsedServiceConfig )
322322 .build ();
323- listener .onResult (result );
323+ listener .onResult2 (result );
324324 receivedConfig = true ;
325325 }
326326
@@ -395,6 +395,9 @@ public Result selectConfig(PickSubchannelArgs args) {
395395 String path = "/" + args .getMethodDescriptor ().getFullMethodName ();
396396 do {
397397 routingCfg = routingConfig ;
398+ if (routingCfg .errorStatus != null ) {
399+ return Result .forError (routingCfg .errorStatus );
400+ }
398401 selectedRoute = null ;
399402 for (RouteData route : routingCfg .routes ) {
400403 if (RoutingUtils .matchRoute (route .routeMatch , path , headers , random )) {
@@ -626,19 +629,6 @@ private static String prefixedClusterSpecifierPluginName(String pluginName) {
626629 return "cluster_specifier_plugin:" + pluginName ;
627630 }
628631
629- private static final class FailingConfigSelector extends InternalConfigSelector {
630- private final Result result ;
631-
632- public FailingConfigSelector (Status error ) {
633- this .result = Result .forError (error );
634- }
635-
636- @ Override
637- public Result selectConfig (PickSubchannelArgs args ) {
638- return result ;
639- }
640- }
641-
642632 private class ResolveState implements ResourceWatcher <XdsListenerResource .LdsUpdate > {
643633 private final ConfigOrError emptyServiceConfig =
644634 serviceConfigParser .parseServiceConfig (Collections .<String , Object >emptyMap ());
@@ -835,13 +825,13 @@ private void updateRoutes(List<VirtualHost> virtualHosts, long httpMaxStreamDura
835825 }
836826 }
837827 // Update service config to include newly added clusters.
838- if (shouldUpdateResult ) {
828+ if (shouldUpdateResult && routingConfig != null ) {
839829 updateResolutionResult ();
830+ shouldUpdateResult = false ;
840831 }
841832 // Make newly added clusters selectable by config selector and deleted clusters no longer
842833 // selectable.
843834 routingConfig = new RoutingConfig (httpMaxStreamDurationNano , routesData .build ());
844- shouldUpdateResult = false ;
845835 for (String cluster : deletedClusters ) {
846836 int count = clusterRefs .get (cluster ).refCount .decrementAndGet ();
847837 if (count == 0 ) {
@@ -893,6 +883,9 @@ private ClientInterceptor createFilters(
893883 }
894884
895885 private void cleanUpRoutes (String error ) {
886+ String errorWithNodeId =
887+ error + ", xDS node ID: " + xdsClient .getBootstrapInfo ().node ().getId ();
888+ routingConfig = new RoutingConfig (Status .UNAVAILABLE .withDescription (errorWithNodeId ));
896889 if (existingClusters != null ) {
897890 for (String cluster : existingClusters ) {
898891 int count = clusterRefs .get (cluster ).refCount .decrementAndGet ();
@@ -902,17 +895,12 @@ private void cleanUpRoutes(String error) {
902895 }
903896 existingClusters = null ;
904897 }
905- routingConfig = RoutingConfig . EMPTY ;
898+
906899 // Without addresses the default LB (normally pick_first) should become TRANSIENT_FAILURE, and
907- // the config selector handles the error message itself. Once the LB API allows providing
908- // failure information for addresses yet still providing a service config, the config seector
909- // could be avoided.
910- String errorWithNodeId =
911- error + ", xDS node ID: " + xdsClient .getBootstrapInfo ().node ().getId ();
912- listener .onResult (ResolutionResult .newBuilder ()
900+ // the config selector handles the error message itself.
901+ listener .onResult2 (ResolutionResult .newBuilder ()
913902 .setAttributes (Attributes .newBuilder ()
914- .set (InternalConfigSelector .KEY ,
915- new FailingConfigSelector (Status .UNAVAILABLE .withDescription (errorWithNodeId )))
903+ .set (InternalConfigSelector .KEY , configSelector )
916904 .build ())
917905 .setServiceConfig (emptyServiceConfig )
918906 .build ());
@@ -983,12 +971,19 @@ public void onResourceDoesNotExist(final String resourceName) {
983971 private static class RoutingConfig {
984972 private final long fallbackTimeoutNano ;
985973 final ImmutableList <RouteData > routes ;
986-
987- private static final RoutingConfig EMPTY = new RoutingConfig (0 , ImmutableList .of ());
974+ final Status errorStatus ;
988975
989976 private RoutingConfig (long fallbackTimeoutNano , ImmutableList <RouteData > routes ) {
990977 this .fallbackTimeoutNano = fallbackTimeoutNano ;
991978 this .routes = checkNotNull (routes , "routes" );
979+ this .errorStatus = null ;
980+ }
981+
982+ private RoutingConfig (Status errorStatus ) {
983+ this .fallbackTimeoutNano = 0 ;
984+ this .routes = null ;
985+ this .errorStatus = checkNotNull (errorStatus , "errorStatus" );
986+ checkArgument (!errorStatus .isOk (), "errorStatus should not be okay" );
992987 }
993988 }
994989
0 commit comments