@@ -58,7 +58,7 @@ final class PriorityLoadBalancer extends LoadBalancer {
5858 private final XdsLogger logger ;
5959
6060 // Includes all active and deactivated children. Mutable. New entries are only added from priority
61- // 0 up to the selected priority. An entry is only deleted 15 minutes after the its deactivation.
61+ // 0 up to the selected priority. An entry is only deleted 15 minutes after its deactivation.
6262 private final Map <String , ChildLbState > children = new HashMap <>();
6363
6464 // Following fields are only null initially.
@@ -70,6 +70,8 @@ final class PriorityLoadBalancer extends LoadBalancer {
7070 @ Nullable private String currentPriority ;
7171 private ConnectivityState currentConnectivityState ;
7272 private SubchannelPicker currentPicker ;
73+ // Set to true if currently in the process of handling resolved addresses.
74+ private boolean handlingResolvedAddresses ;
7375
7476 PriorityLoadBalancer (Helper helper ) {
7577 this .helper = checkNotNull (helper , "helper" );
@@ -94,11 +96,13 @@ public boolean acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
9496 children .get (priority ).deactivate ();
9597 }
9698 }
99+ handlingResolvedAddresses = true ;
97100 for (String priority : priorityNames ) {
98101 if (children .containsKey (priority )) {
99102 children .get (priority ).updateResolvedAddresses ();
100103 }
101104 }
105+ handlingResolvedAddresses = false ;
102106 tryNextPriority ();
103107 return true ;
104108 }
@@ -134,8 +138,11 @@ private void tryNextPriority() {
134138 ChildLbState child =
135139 new ChildLbState (priority , priorityConfigs .get (priority ).ignoreReresolution );
136140 children .put (priority , child );
137- child .updateResolvedAddresses ();
138141 updateOverallState (priority , CONNECTING , BUFFER_PICKER );
142+ // Calling the child's updateResolvedAddresses() can result in tryNextPriority() being
143+ // called recursively. We need to be sure to be done with processing here before it is
144+ // called.
145+ child .updateResolvedAddresses ();
139146 return ; // Give priority i time to connect.
140147 }
141148 ChildLbState child = children .get (priority );
@@ -298,32 +305,33 @@ public void refreshNameResolution() {
298305 @ Override
299306 public void updateBalancingState (final ConnectivityState newState ,
300307 final SubchannelPicker newPicker ) {
301- syncContext .execute (new Runnable () {
302- @ Override
303- public void run () {
304- if (!children .containsKey (priority )) {
305- return ;
306- }
307- connectivityState = newState ;
308- picker = newPicker ;
309- if (deletionTimer != null && deletionTimer .isPending ()) {
310- return ;
311- }
312- if (newState .equals (CONNECTING ) ) {
313- if (!failOverTimer .isPending () && seenReadyOrIdleSinceTransientFailure ) {
314- failOverTimer = syncContext .schedule (new FailOverTask (), 10 , TimeUnit .SECONDS ,
315- executor );
316- }
317- } else if (newState .equals (READY ) || newState .equals (IDLE )) {
318- seenReadyOrIdleSinceTransientFailure = true ;
319- failOverTimer .cancel ();
320- } else if (newState .equals (TRANSIENT_FAILURE )) {
321- seenReadyOrIdleSinceTransientFailure = false ;
322- failOverTimer .cancel ();
323- }
324- tryNextPriority ();
308+ if (!children .containsKey (priority )) {
309+ return ;
310+ }
311+ connectivityState = newState ;
312+ picker = newPicker ;
313+
314+ if (deletionTimer != null && deletionTimer .isPending ()) {
315+ return ;
316+ }
317+ if (newState .equals (CONNECTING )) {
318+ if (!failOverTimer .isPending () && seenReadyOrIdleSinceTransientFailure ) {
319+ failOverTimer = syncContext .schedule (new FailOverTask (), 10 , TimeUnit .SECONDS ,
320+ executor );
325321 }
326- });
322+ } else if (newState .equals (READY ) || newState .equals (IDLE )) {
323+ seenReadyOrIdleSinceTransientFailure = true ;
324+ failOverTimer .cancel ();
325+ } else if (newState .equals (TRANSIENT_FAILURE )) {
326+ seenReadyOrIdleSinceTransientFailure = false ;
327+ failOverTimer .cancel ();
328+ }
329+
330+ // If we are currently handling newly resolved addresses, let's not try to reconfigure as
331+ // the address handling process will take care of that to provide an atomic config update.
332+ if (!handlingResolvedAddresses ) {
333+ tryNextPriority ();
334+ }
327335 }
328336
329337 @ Override
0 commit comments