@@ -173,6 +173,7 @@ public void testRerouteIsNotCalledInAnAllNodesAreHotSpottingCluster() {
173173 final TestState testState = createTestStateWithNumberOfNodesAndHotSpots (
174174 numberOfIndexNodes ,
175175 randomIntBetween (1 , 5 ), // Search nodes should not be considered to address write load hot-spots.
176+ randomIntBetween (1 , 5 ), // ML nodes should not be considered to address write load hot-spots.
176177 numberOfIndexNodes
177178 );
178179 final WriteLoadConstraintMonitor writeLoadConstraintMonitor = new WriteLoadConstraintMonitor (
@@ -282,7 +283,7 @@ public void testRerouteIsCalledBeforeMinimumIntervalHasPassedIfNewNodesBecomeHot
282283 Map <String , NodeUsageStatsForThreadPools > nodeUsageStatsWithExtraHotSpot = new HashMap <>();
283284 for (var entry : testState .clusterInfo .getNodeUsageStatsForThreadPools ().entrySet ()) {
284285 if (thresholdIncreased .get () == false
285- && nonSearchNodeBelowQueueLatencyThreshold (
286+ && indexingNodeBelowQueueLatencyThreshold (
286287 testState .clusterState ,
287288 entry .getKey (),
288289 entry .getValue (),
@@ -316,13 +317,15 @@ && nonSearchNodeBelowQueueLatencyThreshold(
316317 verify (testState .mockRerouteService ).reroute (anyString (), eq (Priority .NORMAL ), any ());
317318 }
318319
319- private boolean nonSearchNodeBelowQueueLatencyThreshold (
320+ private boolean indexingNodeBelowQueueLatencyThreshold (
320321 ClusterState clusterState ,
321322 String nodeId ,
322323 NodeUsageStatsForThreadPools nodeUsageStats ,
323324 long latencyThresholdMillis
324325 ) {
325- return clusterState .getNodes ().get (nodeId ).getRoles ().contains (DiscoveryNodeRole .SEARCH_ROLE ) == false
326+ final var nodeRoles = clusterState .getNodes ().get (nodeId ).getRoles ();
327+ return nodeRoles .contains (DiscoveryNodeRole .SEARCH_ROLE ) == false
328+ && nodeRoles .contains (DiscoveryNodeRole .ML_ROLE ) == false
326329 && nodeUsageStats .threadPoolUsageStatsMap ()
327330 .get (ThreadPool .Names .WRITE )
328331 .maxThreadPoolQueueLatencyMillis () < latencyThresholdMillis ;
@@ -331,12 +334,18 @@ private boolean nonSearchNodeBelowQueueLatencyThreshold(
331334 private TestState createRandomTestStateThatWillTriggerReroute () {
332335 int numberOfNodes = randomIntBetween (3 , 10 );
333336 int numberOfHotSpottingNodes = numberOfNodes - 2 ; // Leave at least 2 non-hot-spotting nodes.
334- return createTestStateWithNumberOfNodesAndHotSpots (numberOfNodes , randomIntBetween (0 , 5 ), numberOfHotSpottingNodes );
337+ return createTestStateWithNumberOfNodesAndHotSpots (
338+ numberOfNodes ,
339+ randomIntBetween (0 , 5 ), // search nodes
340+ randomIntBetween (0 , 2 ), // ML nodes
341+ numberOfHotSpottingNodes
342+ );
335343 }
336344
337345 private TestState createTestStateWithNumberOfNodesAndHotSpots (
338346 int numberOfIndexNodes ,
339347 int numberOfSearchNodes ,
348+ int numberOfMLNodes ,
340349 int numberOfHotSpottingNodes
341350 ) {
342351 assert numberOfHotSpottingNodes <= numberOfIndexNodes ;
@@ -350,8 +359,9 @@ private TestState createTestStateWithNumberOfNodesAndHotSpots(
350359 final ClusterState state = ClusterStateCreationUtils .buildServerlessRoleNodes (
351360 randomIdentifier (), // index name
352361 randomIntBetween (1 , numberOfIndexNodes ), // num shard primaries
353- numberOfIndexNodes , // number of index role nodes
354- numberOfSearchNodes // number of search role nodes
362+ numberOfIndexNodes ,
363+ numberOfSearchNodes ,
364+ numberOfMLNodes
355365 );
356366
357367 final RerouteService rerouteService = mock (RerouteService .class );
@@ -400,7 +410,8 @@ private static ClusterSettings createClusterSettings(
400410 /**
401411 * Create a {@link ClusterInfo} with the specified number of hot spotting index nodes,
402412 * all other index nodes will have no queue latency and have utilization below the specified
403- * high-utilization threshold. Any search nodes in the cluster will have zero usage write load stats.
413+ * high-utilization threshold. Any search or ML nodes in the cluster will have zero usage
414+ * write load stats.
404415 *
405416 * @param state The cluster state
406417 * @param numberOfNodesHotSpotting The number of nodes that should be hot-spotting
@@ -429,8 +440,8 @@ private static ClusterInfo createClusterInfoWithHotSpots(
429440 final AtomicInteger hotSpottingNodes = new AtomicInteger (numberOfNodesHotSpotting );
430441 return ClusterInfo .builder ()
431442 .nodeUsageStatsForThreadPools (state .nodes ().stream ().collect (Collectors .toMap (DiscoveryNode ::getId , node -> {
432- if (node .getRoles ().contains (DiscoveryNodeRole .SEARCH_ROLE )) {
433- // Search nodes are skipped for write load hot-spots.
443+ if (node .getRoles ().contains (DiscoveryNodeRole .SEARCH_ROLE ) || node . getRoles (). contains ( DiscoveryNodeRole . ML_ROLE ) ) {
444+ // Search & ML nodes are skipped for write load hot-spots.
434445 return new NodeUsageStatsForThreadPools (node .getId (), ZERO_USAGE_THREAD_POOL_USAGE_MAP );
435446 }
436447 if (hotSpottingNodes .getAndDecrement () > 0 ) {
0 commit comments