@@ -63,19 +63,16 @@ public class StoppableInstancesSelector {
6363 private final MaintenanceManagementService _maintenanceService ;
6464 private final ClusterTopology _clusterTopology ;
6565 private final ZKHelixDataAccessor _dataAccessor ;
66- private final boolean _preserveOrder ;
6766
6867 private StoppableInstancesSelector (String clusterId , List <String > orderOfZone ,
6968 String customizedInput , MaintenanceManagementService maintenanceService ,
70- ClusterTopology clusterTopology , ZKHelixDataAccessor dataAccessor ,
71- boolean preserveOrder ) {
69+ ClusterTopology clusterTopology , ZKHelixDataAccessor dataAccessor ) {
7270 _clusterId = clusterId ;
7371 _orderOfZone = orderOfZone ;
7472 _customizedInput = customizedInput ;
7573 _maintenanceService = maintenanceService ;
7674 _clusterTopology = clusterTopology ;
7775 _dataAccessor = dataAccessor ;
78- _preserveOrder = preserveOrder ;
7976 }
8077
8178 /**
@@ -86,14 +83,15 @@ private StoppableInstancesSelector(String clusterId, List<String> orderOfZone,
8683 *
8784 * @param instances A list of instance to be evaluated.
8885 * @param toBeStoppedInstances A list of instances presumed to be already stopped
86+ * @param preserveOrder Indicates whether to preserve the original order of instances
8987 * @return An ObjectNode containing:
9088 * - 'stoppableNode': List of instances that can be stopped.
9189 * - 'instance_not_stoppable_with_reasons': A map with the instance name as the key and
9290 * a list of getZoneBasedInstancesreasons for non-stoppability as the value.
9391 * @throws IOException
9492 */
9593 public ObjectNode getStoppableInstancesInSingleZone (List <String > instances ,
96- List <String > toBeStoppedInstances ) throws IOException {
94+ List <String > toBeStoppedInstances , boolean preserveOrder ) throws IOException {
9795 ObjectNode result = JsonNodeFactory .instance .objectNode ();
9896 ArrayNode stoppableInstances =
9997 result .putArray (InstancesAccessor .InstancesProperties .instance_stoppable_parallel .name ());
@@ -102,9 +100,9 @@ public ObjectNode getStoppableInstancesInSingleZone(List<String> instances,
102100 Set <String > toBeStoppedInstancesSet = findToBeStoppedInstances (toBeStoppedInstances );
103101
104102 List <String > zoneBasedInstance =
105- getZoneBasedInstances (instances , _clusterTopology .toZoneMapping ());
103+ getZoneBasedInstances (instances , _clusterTopology .toZoneMapping (), preserveOrder );
106104 populateStoppableInstances (zoneBasedInstance , toBeStoppedInstancesSet , stoppableInstances ,
107- failedStoppableInstances , _preserveOrder );
105+ failedStoppableInstances , preserveOrder );
108106 processNonexistentInstances (instances , failedStoppableInstances );
109107
110108 return result ;
@@ -117,6 +115,7 @@ public ObjectNode getStoppableInstancesInSingleZone(List<String> instances,
117115 *
118116 * @param instances A list of instance to be evaluated.
119117 * @param toBeStoppedInstances A list of instances presumed to be already stopped
118+ * @param preserveOrder Indicates whether to preserve the original order of instances
120119 * @return An ObjectNode containing:
121120 * - 'stoppableNode': List of instances that can be stopped.
122121 * - 'instance_not_stoppable_with_reasons': A map with the instance name as the key and
@@ -154,6 +153,7 @@ public ObjectNode getStoppableInstancesCrossZones(List<String> instances,
154153 *
155154 * @param instances A list of instance to be evaluated.
156155 * @param toBeStoppedInstances A list of instances presumed to be already stopped
156+ * @param preserveOrder Indicates whether to preserve the original order of instances
157157 * @return An ObjectNode containing:
158158 * - 'stoppableNode': List of instances that can be stopped.
159159 * - 'instance_not_stoppable_with_reasons': A map with the instance name as the key and
@@ -266,36 +266,37 @@ public void calculateOrderOfZone(List<String> instances, boolean random) {
266266 *
267267 * @param instances List of instances to be considered
268268 * @param zoneMapping Mapping from zone to instances
269+ * @param preserveOrder Indicates whether to preserve the original order of instances
269270 * @return List of instances in the first non-empty zone. If preserveOrder is true, the original order
270271 * of instances is maintained. If preserveOrder is false (default), instances are sorted lexicographically.
271272 */
272273 private List <String > getZoneBasedInstances (List <String > instances ,
273- Map <String , Set <String >> zoneMapping ) {
274+ Map <String , Set <String >> zoneMapping , boolean preserveOrder ) {
274275 if (_orderOfZone .isEmpty ()) {
275- return _orderOfZone ;
276+ return Collections . emptyList () ;
276277 }
277278
278- Set <String > instanceSet = null ;
279279 for (String zone : _orderOfZone ) {
280- if ( _preserveOrder ) {
281- List < String > filteredInstances = new ArrayList <>( instances );
282- Set < String > currentZoneInstanceSet = new HashSet <>( zoneMapping . get ( zone )) ;
283- filteredInstances . removeIf ( instance -> ! currentZoneInstanceSet . contains ( instance ));
284- if (! filteredInstances . isEmpty ()) {
285- return filteredInstances ;
286- }
287- } else {
288- // Original behavior - lexicographical ordering via TreeSet
289- instanceSet = new TreeSet <>( instances );
290- Set < String > currentZoneInstanceSet = new HashSet <>( zoneMapping . get ( zone ));
291- instanceSet . retainAll ( currentZoneInstanceSet );
292- if (!instanceSet . isEmpty () ) {
293- return new ArrayList <>( instanceSet );
280+ Set < String > currentZoneInstanceSet = zoneMapping . get ( zone );
281+ if ( currentZoneInstanceSet == null || currentZoneInstanceSet . isEmpty ()) {
282+ continue ;
283+ }
284+
285+ // Filter instances based on current zone
286+ List < String > filteredInstances = instances . stream ()
287+ . filter ( currentZoneInstanceSet :: contains )
288+ . collect ( Collectors . toList ());
289+
290+ if (! filteredInstances . isEmpty ()) {
291+ // If preserve order is not required, return sorted list
292+ if (!preserveOrder ) {
293+ Collections . sort ( filteredInstances ); // Lexicographical order
294294 }
295+ return filteredInstances ;
295296 }
296297 }
297298
298- return Collections .EMPTY_LIST ;
299+ return Collections .emptyList () ;
299300 }
300301
301302 /**
@@ -343,7 +344,6 @@ public static class StoppableInstancesSelectorBuilder {
343344 private MaintenanceManagementService _maintenanceService ;
344345 private ClusterTopology _clusterTopology ;
345346 private ZKHelixDataAccessor _dataAccessor ;
346- private boolean _preserveOrder = false ; // Default to false for backward compatibility
347347
348348 public StoppableInstancesSelectorBuilder setClusterId (String clusterId ) {
349349 _clusterId = clusterId ;
@@ -376,14 +376,9 @@ public StoppableInstancesSelectorBuilder setDataAccessor(ZKHelixDataAccessor dat
376376 return this ;
377377 }
378378
379- public StoppableInstancesSelectorBuilder setPreserveOrder (boolean preserveOrder ) {
380- _preserveOrder = preserveOrder ;
381- return this ;
382- }
383-
384379 public StoppableInstancesSelector build () {
385380 return new StoppableInstancesSelector (_clusterId , _orderOfZone , _customizedInput ,
386- _maintenanceService , _clusterTopology , _dataAccessor , _preserveOrder );
381+ _maintenanceService , _clusterTopology , _dataAccessor );
387382 }
388383 }
389384}
0 commit comments