xiangfu0 commented on code in PR #19997:
URL: https://github.com/apache/pinot/pull/19997#discussion_r4343901811


##########
pinot-broker/src/test/java/org/apache/pinot/broker/routing/manager/BrokerRoutingManagerTest.java:
##########
@@ -860,6 +860,36 @@ public void 
testRoutableServerInstanceMapReflectsExclusion() {
     
assertTrue(_routingManager.getRoutableServerInstanceMap().containsKey(SERVER_INSTANCE_ID));
   }
 
+  @Test
+  public void 
testShuttingDownServerRemovedFromRoutingWhileAnotherServerIsExcluded()
+      throws Exception {
+    // Enable three servers, then exclude one of them (simulating 
FailureDetector marking it unhealthy)
+    String excludedServer = "Server_excludedhost_8000";
+    String healthyServer = "Server_healthyhost_8000";
+    ZNRecord serverConfig = createEnabledServerZNRecord(SERVER_INSTANCE_ID);
+    ZNRecord excludedServerConfig = 
createEnabledServerZNRecord(excludedServer);
+    ZNRecord healthyServerConfig = createEnabledServerZNRecord(healthyServer);
+    when(_zkDataAccessor.getChildren(eq(INSTANCE_CONFIGS_PATH), any(), 
eq(AccessOption.PERSISTENT), anyInt(), anyInt()))
+        .thenReturn(List.of(serverConfig, excludedServerConfig, 
healthyServerConfig));
+    _routingManager.processClusterChange(ChangeType.INSTANCE_CONFIG);
+    _routingManager.excludeServerFromRouting(excludedServer);
+    InstanceSelector instanceSelector = mock(InstanceSelector.class);
+    putRoutingEntry(TEST_TABLE, createRoutingEntry(TEST_TABLE, null, null, 
Map.of(), instanceSelector, false));
+
+    // The server starts shutting down while the other server is still excluded
+    ZNRecord shuttingDownServerConfig = 
createEnabledServerZNRecord(SERVER_INSTANCE_ID);
+    shuttingDownServerConfig.setSimpleField(Helix.IS_SHUTDOWN_IN_PROGRESS, 
"true");
+    when(_zkDataAccessor.getChildren(eq(INSTANCE_CONFIGS_PATH), any(), 
eq(AccessOption.PERSISTENT), anyInt(), anyInt()))
+        .thenReturn(List.of(shuttingDownServerConfig, excludedServerConfig, 
healthyServerConfig));
+    _routingManager.processClusterChange(ChangeType.INSTANCE_CONFIG);
+
+    // The routing entry must stop selecting the shutting down server, and 
only the healthy server stays routable
+    verify(instanceSelector).onInstancesChange(Set.of(healthyServer), 
List.of(SERVER_INSTANCE_ID));

Review Comment:
   Good targeted regression test — I confirmed it fails on the pre-fix code and 
passes here. The `onInstancesChange(Set.of(healthyServer), 
List.of(SERVER_INSTANCE_ID))` assertion pins down both the routable set and the 
exact changed list, which is what the bug corrupted. Minor optional nit: a 
one-line comment that the routing entry is added *after* the exclusion (so this 
verify captures only the shutdown-triggered callback, not the earlier exclusion 
one) would save the next reader a moment of head-scratching.



##########
pinot-broker/src/main/java/org/apache/pinot/broker/routing/manager/BaseBrokerRoutingManager.java:
##########
@@ -486,21 +486,14 @@ private void processInstanceConfigChangeInternal() {
       }
     }
 
-    // Calculate the routable servers and the changed routable servers
+    // Calculate the routable servers and the changed servers
+    // NOTE: All new enabled servers are routable because they are removed 
from the excluded servers above. All new
+    //       disabled servers are counted as changed, even excluded ones whose 
routing does not change, so that the
+    //       early termination below cannot skip removing them from 
_enabledServerInstanceMap.
     List<String> changedServers = new ArrayList<>(newEnabledServers.size() + 
newDisabledServers.size());
-    if (_excludedServers.isEmpty()) {
-      changedServers.addAll(newEnabledServers);
-      changedServers.addAll(newDisabledServers);
-    } else {
-      enabledServers.removeAll(_excludedServers);
-      // NOTE: All new enabled servers are routable
-      changedServers.addAll(newEnabledServers);
-      for (String newDisabledServer : newDisabledServers) {
-        if (_excludedServers.contains(newDisabledServer)) {
-          changedServers.add(newDisabledServer);
-        }
-      }
-    }
+    changedServers.addAll(newEnabledServers);
+    changedServers.addAll(newDisabledServers);
+    enabledServers.removeAll(_excludedServers);

Review Comment:
   Nice simplification. `removeAll` is now called unconditionally, which is a 
no-op when `_excludedServers` is empty, so the two branches collapse cleanly 
with no behavior change for the common case. The added NOTE explaining *why* 
excluded disabled servers are still counted (to keep the early return from 
skipping their removal) is exactly the context a future reader needs. No change 
requested.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to