3636
3737public class WriteLoadConstraintDeciderTests extends ESAllocationTestCase {
3838
39- // NOMERGE: I wonder if we don't want a node utilization percent, but rather a total node execution time used and a total node execution
40- // time possible. The math would be a whole lot easier on us...
41- public void testWriteLoadDeciderIsDisabled () {
39+ public void testWriteLoadDecider () {
4240 String indexName = "test-index" ;
4341
44- // Set up multiple nodes and an index with multiple shards.
45- // DiscoveryNode discoveryNode1 = newNode("node1");
46- // DiscoveryNode discoveryNode2 = newNode("node2");
47- // ShardId shardId1 = new ShardId(indexName, IndexMetadata.INDEX_UUID_NA_VALUE, 0);
48- // ShardId shardId2 = new ShardId(indexName, IndexMetadata.INDEX_UUID_NA_VALUE, 1);
49-
5042 /**
51- * Create the ClusterState
43+ * Create the ClusterState for multiple nodes and multiple index shards.
5244 */
5345
54- ClusterState clusterState = ClusterStateCreationUtils .stateWithAssignedPrimariesAndReplicas (new String [] { indexName }, 3 , 0 );
55- assertEquals (2 , clusterState .nodes ().size ());
46+ ClusterState clusterState = ClusterStateCreationUtils .stateWithAssignedPrimariesAndReplicas (new String [] { indexName }, 3 , 1 );
47+ // The number of data nodes the util method above creates is numberOfReplicas+1.
48+ assertEquals (3 , clusterState .nodes ().size ());
5649 assertEquals (1 , clusterState .metadata ().getTotalNumberOfIndices ());
5750
5851 /**
59- * Fetch the nodes and index shards from the generated ClusterState.
52+ * Fetch references to the nodes and index shards from the generated ClusterState, so the ClusterInfo can be created from them .
6053 */
6154
6255 var discoveryNodeIterator = clusterState .nodes ().iterator ();
6356 assertTrue (discoveryNodeIterator .hasNext ());
6457 var exceedingThresholdDiscoveryNode = discoveryNodeIterator .next ();
6558 assertTrue (discoveryNodeIterator .hasNext ());
6659 var belowThresholdDiscoveryNode2 = discoveryNodeIterator .next ();
60+ assertTrue (discoveryNodeIterator .hasNext ());
61+ var nearThresholdDiscoveryNode3 = discoveryNodeIterator .next ();
6762 assertFalse (discoveryNodeIterator .hasNext ());
6863
6964 var indexIterator = clusterState .metadata ().indicesAllProjects ().iterator ();
@@ -74,10 +69,10 @@ public void testWriteLoadDeciderIsDisabled() {
7469 assertEquals (3 , testIndexMetadata .getNumberOfShards ());
7570 ShardId testShardId1 = new ShardId (testIndex , 0 );
7671 ShardId testShardId2 = new ShardId (testIndex , 1 );
77- ShardId testShardId3NoWriteLoad = new ShardId (testIndex , 1 );
72+ ShardId testShardId3NoWriteLoad = new ShardId (testIndex , 2 );
7873
7974 /**
80- * Create the ClusterInfo that includes the node and shard level write load estimates.
75+ * Create a ClusterInfo that includes the node and shard level write load estimates for a variety of node capacity situations .
8176 */
8277
8378 var nodeThreadPoolStatsWithWriteExceedingThreshold = createNodeUsageStatsForThreadPools (
@@ -87,15 +82,18 @@ public void testWriteLoadDeciderIsDisabled() {
8782 0
8883 );
8984 var nodeThreadPoolStatsWithWriteBelowThreshold = createNodeUsageStatsForThreadPools (belowThresholdDiscoveryNode2 , 8 , 0.50f , 0 );
85+ var nodeThreadPoolStatsWithWriteNearThreshold = createNodeUsageStatsForThreadPools (nearThresholdDiscoveryNode3 , 8 , 0.89f , 0 );
9086
9187 // Create a map of usage per node.
9288 var nodeIdToNodeUsageStatsForThreadPools = new HashMap <String , NodeUsageStatsForThreadPools >();
9389 nodeIdToNodeUsageStatsForThreadPools .put (exceedingThresholdDiscoveryNode .getId (), nodeThreadPoolStatsWithWriteExceedingThreshold );
9490 nodeIdToNodeUsageStatsForThreadPools .put (belowThresholdDiscoveryNode2 .getId (), nodeThreadPoolStatsWithWriteBelowThreshold );
91+ nodeIdToNodeUsageStatsForThreadPools .put (nearThresholdDiscoveryNode3 .getId (), nodeThreadPoolStatsWithWriteNearThreshold );
9592
93+ // Create a map of usage per shard.
9694 var shardIdToWriteLoadEstimate = new HashMap <ShardId , Double >();
97- shardIdToWriteLoadEstimate .put (testShardId1 , 1 .5 );
98- shardIdToWriteLoadEstimate .put (testShardId2 , 1 .5 );
95+ shardIdToWriteLoadEstimate .put (testShardId1 , 0 .5 );
96+ shardIdToWriteLoadEstimate .put (testShardId2 , 0 .5 );
9997 shardIdToWriteLoadEstimate .put (testShardId3NoWriteLoad , 0d );
10098
10199 ClusterInfo clusterInfo = ClusterInfo .builder ()
@@ -104,7 +102,7 @@ public void testWriteLoadDeciderIsDisabled() {
104102 .build ();
105103
106104 /**
107- * Create the RoutingAllocation
105+ * Create the RoutingAllocation from the ClusterState and ClusterInfo above, and set up the other input for the WriteLoadDecider.
108106 */
109107
110108 var routingAllocation = new RoutingAllocation (
@@ -138,32 +136,36 @@ public void testWriteLoadDeciderIsDisabled() {
138136 ShardRoutingState .STARTED
139137 );
140138
141- assertTrue (discoveryNodeIterator .hasNext ());
142139 RoutingNode exceedingThresholdRoutingNode = RoutingNodesHelper .routingNode (
143140 exceedingThresholdDiscoveryNode .getId (),
144- discoveryNodeIterator . next () ,
141+ exceedingThresholdDiscoveryNode ,
145142 shardRouting1
146143 );
147- assertTrue (discoveryNodeIterator .hasNext ());
148144 RoutingNode belowThresholdRoutingNode = RoutingNodesHelper .routingNode (
149145 belowThresholdDiscoveryNode2 .getId (),
150- discoveryNodeIterator . next () ,
146+ belowThresholdDiscoveryNode2 ,
151147 shardRouting2
152148 );
153- assertFalse (discoveryNodeIterator .hasNext ());
149+ RoutingNode nearThresholdRoutingNode = RoutingNodesHelper .routingNode (
150+ nearThresholdDiscoveryNode3 .getId (),
151+ nearThresholdDiscoveryNode3 ,
152+ new ShardRouting [] {}
153+ );
154154
155155 /**
156156 * Test the write load decider
157157 */
158158
159159 // The write load decider is disabled by default.
160- var writeLoadDecider = createWriteLoadConstraintDecider (Settings .builder ().build ());
161160
162- assertEquals (Decision .YES , writeLoadDecider .canAllocate (shardRouting2 , exceedingThresholdRoutingNode , routingAllocation ));
163- assertEquals (Decision .YES , writeLoadDecider .canAllocate (shardRouting1 , belowThresholdRoutingNode , routingAllocation ));
164- assertEquals (Decision .YES , writeLoadDecider .canAllocate (thirdRoutingNoWriteLoad , exceedingThresholdRoutingNode , routingAllocation ));
161+ var writeLoadDecider = createWriteLoadConstraintDecider (Settings .builder ().build ());
162+ assertEquals (Decision .Type .YES , writeLoadDecider .canAllocate (shardRouting2 , exceedingThresholdRoutingNode , routingAllocation ).type ());
163+ assertEquals (Decision .Type .YES , writeLoadDecider .canAllocate (shardRouting1 , belowThresholdRoutingNode , routingAllocation ).type ());
164+ assertEquals (Decision .Type .YES , writeLoadDecider .canAllocate (shardRouting1 , nearThresholdRoutingNode , routingAllocation ).type ());
165+ assertEquals (Decision .Type .YES , writeLoadDecider .canAllocate (thirdRoutingNoWriteLoad , exceedingThresholdRoutingNode , routingAllocation ).type ());
165166
166167 // Check that the answers change when enabled.
168+
167169 writeLoadDecider = createWriteLoadConstraintDecider (
168170 Settings .builder ()
169171 .put (
@@ -172,27 +174,26 @@ public void testWriteLoadDeciderIsDisabled() {
172174 )
173175 .build ()
174176 );
175-
176- assertEquals (Decision .NO , writeLoadDecider .canAllocate (shardRouting2 , exceedingThresholdRoutingNode , routingAllocation ));
177- assertEquals (Decision .YES , writeLoadDecider .canAllocate (shardRouting1 , belowThresholdRoutingNode , routingAllocation ));
178- assertEquals (Decision .YES , writeLoadDecider .canAllocate (thirdRoutingNoWriteLoad , exceedingThresholdRoutingNode , routingAllocation ));
179-
180- // NOMERGE: test that adding a shard is rejected if it would overflow the utilization threshold?
181- // Need to implement the logic in the decider, I don't check right now.
182- }
183-
184- public void testShardWithNoWriteLoadEstimateIsAlwaysYES () {
185- Settings writeLoadConstraintSettings = Settings .builder ()
186- .put (
187- WriteLoadConstraintSettings .WRITE_LOAD_DECIDER_ENABLED_SETTING .getKey (),
188- WriteLoadConstraintSettings .WriteLoadDeciderStatus .ENABLED
189- )
190- .build ();
191- // TODO
192- }
193-
194- public void testShardWithWriteLoadEstimate () {
195- // TODO: test successful re-assignment and rejected re-assignment due to threshold
177+ assertEquals (
178+ "Assigning a new shard to a node that is above the threshold should fail" ,
179+ Decision .Type .NO ,
180+ writeLoadDecider .canAllocate (shardRouting2 , exceedingThresholdRoutingNode , routingAllocation ).type ()
181+ );
182+ assertEquals (
183+ "Assigning a new shard to a node that has capacity should succeed" ,
184+ Decision .Type .YES ,
185+ writeLoadDecider .canAllocate (shardRouting1 , belowThresholdRoutingNode , routingAllocation ).type ()
186+ );
187+ assertEquals (
188+ "Assigning a new shard without a write load estimate should _not_ be blocked by lack of capacity" ,
189+ Decision .Type .YES ,
190+ writeLoadDecider .canAllocate (thirdRoutingNoWriteLoad , exceedingThresholdRoutingNode , routingAllocation ).type ()
191+ );
192+ assertEquals (
193+ "Assigning a new shard that would cause the node to exceed capacity should fail" ,
194+ Decision .Type .NO ,
195+ writeLoadDecider .canAllocate (shardRouting1 , nearThresholdRoutingNode , routingAllocation ).type ()
196+ );
196197 }
197198
198199 private WriteLoadConstraintDecider createWriteLoadConstraintDecider (Settings settings ) {
0 commit comments