diff --git a/server/src/test/java/org/elasticsearch/cluster/InternalClusterInfoServiceSchedulingTests.java b/server/src/test/java/org/elasticsearch/cluster/InternalClusterInfoServiceSchedulingTests.java index 1e91f69f47573..f393cf5033bbc 100644 --- a/server/src/test/java/org/elasticsearch/cluster/InternalClusterInfoServiceSchedulingTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/InternalClusterInfoServiceSchedulingTests.java @@ -49,6 +49,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; public class InternalClusterInfoServiceSchedulingTests extends ESTestCase { @@ -56,6 +57,8 @@ public void testScheduling() { final DiscoveryNode discoveryNode = DiscoveryNodeUtils.create("test"); final DiscoveryNodes noMaster = DiscoveryNodes.builder().add(discoveryNode).localNodeId(discoveryNode.getId()).build(); final DiscoveryNodes localMaster = noMaster.withMasterNodeId(discoveryNode.getId()); + final DiscoveryNode joiner = DiscoveryNodeUtils.create("joiner"); + final DiscoveryNodes withJoiner = DiscoveryNodes.builder(localMaster).add(joiner).build(); final Settings.Builder settingsBuilder = Settings.builder() .put(Node.NODE_NAME_SETTING.getKey(), discoveryNode.getName()) @@ -129,6 +132,45 @@ public void reroute(String reason, Priority priority, ActionListener liste ); runUntilFlag(deterministicTaskQueue, becameMaster1); + // A node joins the cluster + { + Mockito.clearInvocations(mockEstimatedHeapUsageCollector, nodeUsageStatsForThreadPoolsCollector); + final int initialRequestCount = client.requestCount; + final AtomicBoolean nodeJoined = new AtomicBoolean(); + clusterApplierService.onNewClusterState( + "node joins", + () -> ClusterState.builder(new ClusterName("cluster")).nodes(withJoiner).build(), + setFlagOnSuccess(nodeJoined) + ); + // Don't use runUntilFlag because we don't want the scheduled task to run + deterministicTaskQueue.runAllRunnableTasks(); + assertTrue(nodeJoined.get()); + // Addition of node should have triggered refresh + // should have run two client requests: nodes stats request and indices stats request + assertThat(client.requestCount, equalTo(initialRequestCount + 2)); + verify(mockEstimatedHeapUsageCollector).collectClusterHeapUsage(any()); // Should have polled for heap usage + verify(nodeUsageStatsForThreadPoolsCollector).collectUsageStats(any(), any(), any()); + } + + // ... then leaves + { + Mockito.clearInvocations(mockEstimatedHeapUsageCollector, nodeUsageStatsForThreadPoolsCollector); + final int initialRequestCount = client.requestCount; + final AtomicBoolean nodeLeft = new AtomicBoolean(); + clusterApplierService.onNewClusterState( + "node leaves", + () -> ClusterState.builder(new ClusterName("cluster")).nodes(localMaster).build(), + setFlagOnSuccess(nodeLeft) + ); + // Don't use runUntilFlag because we don't want the scheduled task to run + deterministicTaskQueue.runAllRunnableTasks(); + assertTrue(nodeLeft.get()); + // departing nodes don't trigger refreshes + assertThat(client.requestCount, equalTo(initialRequestCount)); + verifyNoInteractions(mockEstimatedHeapUsageCollector); + verifyNoInteractions(nodeUsageStatsForThreadPoolsCollector); + } + final AtomicBoolean failMaster1 = new AtomicBoolean(); clusterApplierService.onNewClusterState( "fail master 1",