This is an automated email from the ASF dual-hosted git repository.

kfaraz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 9fca068da23 minor: Fix metric values of costBased auto-scaler (#19641)
9fca068da23 is described below

commit 9fca068da23e5518b2ca9daf366daa2331775840
Author: Kashif Faraz <[email protected]>
AuthorDate: Thu Jul 9 15:38:14 2026 +0530

    minor: Fix metric values of costBased auto-scaler (#19641)
    
    Changes:
    - Add metrics `optimalLagCost`, `optimalIdleCost`
    - These metrics would help relate the cost function to physical quantities
    - Fix the emitted values of `lagWeight` and `idleWeight`
    - Do not emit invalid values for `avgProcessingRate` and `avgPollIdleRatio`
    - Remove unused auto-scaler config field `minTriggerScaleActionFrequency`. 
Use default constants instead.
    - Break up the test method `testComputeValidTaskCounts` into multiple test 
cases
---
 .../CostBasedAutoScalerIntegrationTest.java        |  5 --
 .../supervisor/autoscaler/CostBasedAutoScaler.java | 54 ++++++++----
 .../autoscaler/CostBasedAutoScalerConfig.java      | 47 ++---------
 .../autoscaler/CostBasedAutoScalerConfigTest.java  | 32 ++++----
 .../autoscaler/CostBasedAutoScalerTest.java        | 96 +++++++++-------------
 website/.spelling                                  |  2 -
 6 files changed, 101 insertions(+), 135 deletions(-)

diff --git 
a/embedded-tests/src/test/java/org/apache/druid/testing/embedded/indexing/autoscaler/CostBasedAutoScalerIntegrationTest.java
 
b/embedded-tests/src/test/java/org/apache/druid/testing/embedded/indexing/autoscaler/CostBasedAutoScalerIntegrationTest.java
index 0f7a8ff3048..7066d6d0df4 100644
--- 
a/embedded-tests/src/test/java/org/apache/druid/testing/embedded/indexing/autoscaler/CostBasedAutoScalerIntegrationTest.java
+++ 
b/embedded-tests/src/test/java/org/apache/druid/testing/embedded/indexing/autoscaler/CostBasedAutoScalerIntegrationTest.java
@@ -108,7 +108,6 @@ public class CostBasedAutoScalerIntegrationTest extends 
StreamIndexTestBase
         .taskCountMax(100)
         .taskCountStart(initialTaskCount)
         .scaleActionPeriodMillis(1900)
-        .minTriggerScaleActionFrequencyMillis(2000)
         // Weight configuration: strongly favor lag reduction over idle time
         .lagWeight(0.9)
         .idleWeight(0.1)
@@ -163,7 +162,6 @@ public class CostBasedAutoScalerIntegrationTest extends 
StreamIndexTestBase
         .taskCountMax(50)
         .taskCountStart(lowInitialTaskCount)
         .scaleActionPeriodMillis(500)
-        .minTriggerScaleActionFrequencyMillis(1000)
         .lagWeight(0.8)
         .idleWeight(0.2)
         .build();
@@ -212,7 +210,6 @@ public class CostBasedAutoScalerIntegrationTest extends 
StreamIndexTestBase
         .taskCountMax(50)
         .taskCountStart(lowInitialTaskCount)
         .scaleActionPeriodMillis(500)
-        .minTriggerScaleActionFrequencyMillis(1000)
         .lagWeight(0.8)
         .idleWeight(0.2)
         .usePollIdleRatio(false)
@@ -258,7 +255,6 @@ public class CostBasedAutoScalerIntegrationTest extends 
StreamIndexTestBase
         .taskCountMax(4)
         .lagWeight(0.5)
         .idleWeight(0.5)
-        .minTriggerScaleActionFrequencyMillis(10L)
         .scaleActionPeriodMillis(10L)
         .minScaleDownDelay(Duration.standardSeconds(1))
         .build();
@@ -336,7 +332,6 @@ public class CostBasedAutoScalerIntegrationTest extends 
StreamIndexTestBase
         .taskCountMin(1)
         .taskCountMax(10)
         .scaleActionPeriodMillis(100)
-        .minTriggerScaleActionFrequencyMillis(100)
         // High idle weight ensures scale-down when tasks are mostly idle 
(little data to process)
         .lagWeight(0.1)
         .idleWeight(0.9)
diff --git 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
index bf07545aaa5..b089df3bcd1 100644
--- 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
+++ 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScaler.java
@@ -65,10 +65,15 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
 
   public static final String LAG_WEIGHT_METRIC = 
"task/autoScaler/costBased/lagWeight";
   public static final String IDLE_WEIGHT_METRIC = 
"task/autoScaler/costBased/idleWeight";
+  public static final String CURRENT_LAG_COST_METRIC = 
"task/autoScaler/costBased/currentLagCost";
+  public static final String CURRENT_IDLE_COST_METRIC = 
"task/autoScaler/costBased/currentIdleCost";
+  public static final String OPTIMAL_LAG_COST_METRIC = 
"task/autoScaler/costBased/optimalLagCost";
+  public static final String OPTIMAL_IDLE_COST_METRIC = 
"task/autoScaler/costBased/optimalIdleCost";
   public static final String OPTIMAL_TASK_COUNT_METRIC = 
"task/autoScaler/costBased/optimalTaskCount";
   public static final String INVALID_METRICS_COUNT = 
"task/autoScaler/costBased/invalidMetrics";
   public static final String AVG_PROCESSING_RATE_METRIC = 
"task/autoScaler/costBased/avgProcessingRate";
   public static final String AVG_POLL_IDLE_RATIO = 
"task/autoScaler/costBased/avgPollIdleRatio";
+  public static final String IDLE_RATIO_ESTIMATED_FROM_RATE = 
"task/autoScaler/costBased/idleRatioFromRate";
 
   /**
    * Maximum number of candidate task counts to evaluate above or below the 
current task count
@@ -233,7 +238,6 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
 
     final int[] validTaskCounts = CostBasedAutoScaler.computeValidTaskCounts(
         partitionCount,
-        currentTaskCount,
         config.getTaskCountMin(),
         config.getTaskCountMax()
     );
@@ -245,8 +249,10 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
     }
 
     // Start with the current task count as optimal
+    final CostResult currentCost = costFunction.computeCost(metrics, 
currentTaskCount, config);
     int optimalTaskCount = currentTaskCount;
-    CostResult optimalCost = costFunction.computeCost(metrics, 
currentTaskCount, config);
+    CostResult optimalCost = currentCost;
+    final double idleRatioEstimatedFromRate = 
metrics.estimateIdleRatioFromProcessingRate();
 
     log.info(
         "Computing optimal taskCount for supervisor[%s] with metrics:"
@@ -257,7 +263,7 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
         metrics.getAvgPartitionLag(),
         metrics.getAvgProcessingRate(),
         metrics.getMaxObservedRate(),
-        metrics.estimateIdleRatioFromProcessingRate(),
+        idleRatioEstimatedFromRate,
         metrics.getPollIdleRatio(),
         config.getLagWeight(),
         config.getIdleWeight()
@@ -297,16 +303,29 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
     }
 
     emitter.emit(getMetricBuilder().setMetric(OPTIMAL_TASK_COUNT_METRIC, 
(long) optimalTaskCount));
-    emitter.emit(getMetricBuilder().setMetric(LAG_WEIGHT_METRIC, 
optimalCost.lagCost()));
-    emitter.emit(getMetricBuilder().setMetric(IDLE_WEIGHT_METRIC, 
optimalCost.idleCost()));
-    emitter.emit(getMetricBuilder().setMetric(AVG_PROCESSING_RATE_METRIC, 
metrics.getAvgProcessingRate()));
-    emitter.emit(getMetricBuilder().setMetric(AVG_POLL_IDLE_RATIO, 
metrics.getPollIdleRatio()));
+    emitter.emit(getMetricBuilder().setMetric(LAG_WEIGHT_METRIC, 
config.getLagWeight()));
+    emitter.emit(getMetricBuilder().setMetric(IDLE_WEIGHT_METRIC, 
config.getIdleWeight()));
+    emitter.emit(getMetricBuilder().setMetric(CURRENT_LAG_COST_METRIC, 
currentCost.lagCost()));
+    emitter.emit(getMetricBuilder().setMetric(CURRENT_IDLE_COST_METRIC, 
currentCost.idleCost()));
+
+    // Emit avg rate and idle metrics only if they are available
+    if (metrics.getAvgProcessingRate() >= 0) {
+      emitter.emit(getMetricBuilder().setMetric(AVG_PROCESSING_RATE_METRIC, 
metrics.getAvgProcessingRate()));
+    }
+    if (metrics.getPollIdleRatio() >= 0) {
+      emitter.emit(getMetricBuilder().setMetric(AVG_POLL_IDLE_RATIO, 
metrics.getPollIdleRatio()));
+    }
+    if (idleRatioEstimatedFromRate >= 0) {
+      
emitter.emit(getMetricBuilder().setMetric(IDLE_RATIO_ESTIMATED_FROM_RATE, 
idleRatioEstimatedFromRate));
+    }
 
     if (optimalTaskCount != currentTaskCount) {
       log.info(
           "Optimal taskCount[%d] for supervisor[%s] has lowest cost[%.4f] out 
of the following candidates: %n%s",
           optimalTaskCount, supervisorId, optimalCost.totalCost(), 
constructCostTable(validTaskCounts, costResults)
       );
+      emitter.emit(getMetricBuilder().setMetric(OPTIMAL_LAG_COST_METRIC, 
optimalCost.lagCost()));
+      emitter.emit(getMetricBuilder().setMetric(OPTIMAL_IDLE_COST_METRIC, 
optimalCost.idleCost()));
     }
 
     // Scale-up is applied eagerly; scale-down may be deferred by 
computeTaskCountForScaleAction().
@@ -317,17 +336,16 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
    * Generates valid task counts by converting every possible 
partitions-per-task ratio
    * into a task count and filtering by configured min/max task count bounds.
    *
-   * @return list of valid task counts within bounds
+   * @return array of valid task counts within bounds
    */
   @SuppressWarnings({"ReassignedVariable"})
   static int[] computeValidTaskCounts(
       int partitionCount,
-      int currentTaskCount,
       int taskCountMin,
       int taskCountMax
   )
   {
-    if (partitionCount <= 0 || currentTaskCount <= 0) {
+    if (partitionCount <= 0) {
       return new int[]{};
     }
 
@@ -368,8 +386,12 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
           if (autoScalerMetricsMap instanceof Map) {
             Object pollIdleRatioAvg = ((Map<?, ?>) 
autoScalerMetricsMap).get(SeekableStreamIndexTaskRunner.POLL_IDLE_RATIO_KEY);
             if (pollIdleRatioAvg instanceof Number) {
-              sum += ((Number) pollIdleRatioAvg).doubleValue();
-              count++;
+              double taskPollIdleRatio = ((Number) 
pollIdleRatioAvg).doubleValue();
+              // Do not include negative values
+              if (taskPollIdleRatio >= 0) {
+                sum += taskPollIdleRatio;
+                count++;
+              }
             }
           }
         }
@@ -414,8 +436,12 @@ public class CostBasedAutoScaler implements 
SupervisorTaskAutoScaler
               if (movingAvgObj instanceof Map) {
                 Object processedRate = ((Map<?, ?>) 
movingAvgObj).get(RowIngestionMeters.PROCESSED);
                 if (processedRate instanceof Number) {
-                  sum += ((Number) processedRate).doubleValue();
-                  count++;
+                  // Do not include negative values
+                  double taskProcessedRate = ((Number) 
processedRate).doubleValue();
+                  if (taskProcessedRate >= 0) {
+                    sum += taskProcessedRate;
+                    count++;
+                  }
                 }
               }
             }
diff --git 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
index fa4d547eae4..785fa3257b5 100644
--- 
a/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
+++ 
b/indexing-service/src/main/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfig.java
@@ -28,7 +28,6 @@ import 
org.apache.druid.indexing.overlord.supervisor.Supervisor;
 import org.apache.druid.indexing.overlord.supervisor.SupervisorSpec;
 import 
org.apache.druid.indexing.overlord.supervisor.autoscaler.SupervisorTaskAutoScaler;
 import 
org.apache.druid.indexing.seekablestream.supervisor.SeekableStreamSupervisor;
-import org.apache.druid.java.util.emitter.EmittingLogger;
 import org.apache.druid.java.util.emitter.service.ServiceEmitter;
 import org.joda.time.Duration;
 
@@ -45,18 +44,15 @@ import java.util.Objects;
 @JsonInclude(JsonInclude.Include.NON_NULL)
 public class CostBasedAutoScalerConfig implements AutoScalerConfig
 {
-  private static final EmittingLogger LOG = new 
EmittingLogger(CostBasedAutoScalerConfig.class);
-
-  static final long DEFAULT_SCALE_ACTION_PERIOD_MILLIS = 10 * 60 * 1000; // 10 
minutes
   static final double DEFAULT_LAG_WEIGHT = 0.4;
   static final double DEFAULT_IDLE_WEIGHT = 0.6;
-  static final Duration DEFAULT_MIN_SCALE_DELAY = 
Duration.millis(DEFAULT_SCALE_ACTION_PERIOD_MILLIS * 3);
+  static final Duration DEFAULT_MIN_SCALE_UP_DELAY = 
Duration.standardMinutes(10);
+  static final Duration DEFAULT_MIN_SCALE_DOWN_DELAY = 
Duration.standardMinutes(30);
 
   private final boolean enableTaskAutoScaler;
   private final int taskCountMax;
   private final int taskCountMin;
   private final Integer taskCountStart;
-  private final long minTriggerScaleActionFrequencyMillis;
   private final Double stopTaskCountRatio;
   private final long scaleActionPeriodMillis;
 
@@ -72,9 +68,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
 
   /**
    * Creates a new CostBasedAutoScalerConfig instance.
-   * <p>
-   * Note: useTaskCountBoundaries and highLagThreshold are kept for backward 
compatibility,
-   * but effectively they are removed.
    */
   @JsonCreator
   public CostBasedAutoScalerConfig(
@@ -82,7 +75,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
       @JsonProperty("taskCountMin") Integer taskCountMin,
       @Nullable @JsonProperty("enableTaskAutoScaler") Boolean 
enableTaskAutoScaler,
       @Nullable @JsonProperty("taskCountStart") Integer taskCountStart,
-      @Nullable @JsonProperty("minTriggerScaleActionFrequencyMillis") Long 
minTriggerScaleActionFrequencyMillis,
       @Nullable @JsonProperty("stopTaskCountRatio") Double stopTaskCountRatio,
       @Nullable @JsonProperty("scaleActionPeriodMillis") Long 
scaleActionPeriodMillis,
       @Nullable @JsonProperty("lagWeight") Double lagWeight,
@@ -96,18 +88,9 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
       @Nullable @JsonProperty("usePollIdleRatio") Boolean usePollIdleRatio
   )
   {
-    this.enableTaskAutoScaler = enableTaskAutoScaler != null ? 
enableTaskAutoScaler : false;
-
-    // Timing configuration with defaults
-    this.scaleActionPeriodMillis = scaleActionPeriodMillis != null
-                                   ? scaleActionPeriodMillis
-                                   : DEFAULT_SCALE_ACTION_PERIOD_MILLIS;
-    this.minTriggerScaleActionFrequencyMillis = Configs.valueOrDefault(
-        minTriggerScaleActionFrequencyMillis,
-        DEFAULT_SCALE_ACTION_PERIOD_MILLIS
-    );
+    this.enableTaskAutoScaler = Configs.valueOrDefault(enableTaskAutoScaler, 
false);
+    this.scaleActionPeriodMillis = 
Configs.valueOrDefault(scaleActionPeriodMillis, 
DEFAULT_MIN_SCALE_UP_DELAY.getMillis());
 
-    // Cost function weights with defaults
     this.lagWeight = Configs.valueOrDefault(lagWeight, DEFAULT_LAG_WEIGHT);
     this.idleWeight = Configs.valueOrDefault(idleWeight, DEFAULT_IDLE_WEIGHT);
     this.optimalTaskIdleRatio = Configs.valueOrDefault(
@@ -116,11 +99,8 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
     );
     this.useTaskCountBoundariesOnScaleUp = 
Configs.valueOrDefault(useTaskCountBoundariesOnScaleUp, false);
     this.useTaskCountBoundariesOnScaleDown = 
Configs.valueOrDefault(useTaskCountBoundariesOnScaleDown, true);
-    this.minScaleUpDelay = Configs.valueOrDefault(
-        minScaleUpDelay,
-        Duration.millis(this.minTriggerScaleActionFrequencyMillis)
-    );
-    this.minScaleDownDelay = Configs.valueOrDefault(minScaleDownDelay, 
DEFAULT_MIN_SCALE_DELAY);
+    this.minScaleUpDelay = Configs.valueOrDefault(minScaleUpDelay, 
DEFAULT_MIN_SCALE_UP_DELAY);
+    this.minScaleDownDelay = Configs.valueOrDefault(minScaleDownDelay, 
DEFAULT_MIN_SCALE_DOWN_DELAY);
     this.scaleDownDuringTaskRolloverOnly = 
Configs.valueOrDefault(scaleDownDuringTaskRolloverOnly, false);
     this.usePollIdleRatio = Configs.valueOrDefault(usePollIdleRatio, true);
 
@@ -204,7 +184,7 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
   @JsonProperty
   public long getMinTriggerScaleActionFrequencyMillis()
   {
-    return minTriggerScaleActionFrequencyMillis;
+    return -1;
   }
 
   @Override
@@ -308,7 +288,7 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
   @Override
   public SupervisorTaskAutoScaler createAutoScaler(Supervisor supervisor, 
SupervisorSpec spec, ServiceEmitter emitter)
   {
-    return new CostBasedAutoScaler((SeekableStreamSupervisor) supervisor, 
this, spec, emitter);
+    return new CostBasedAutoScaler((SeekableStreamSupervisor<?, ?, ?>) 
supervisor, this, spec, emitter);
   }
 
   @Override
@@ -326,7 +306,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
     return enableTaskAutoScaler == that.enableTaskAutoScaler
            && taskCountMax == that.taskCountMax
            && taskCountMin == that.taskCountMin
-           && minTriggerScaleActionFrequencyMillis == 
that.minTriggerScaleActionFrequencyMillis
            && scaleActionPeriodMillis == that.scaleActionPeriodMillis
            && Double.compare(that.lagWeight, lagWeight) == 0
            && Double.compare(that.idleWeight, idleWeight) == 0
@@ -349,7 +328,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
         taskCountMax,
         taskCountMin,
         taskCountStart,
-        minTriggerScaleActionFrequencyMillis,
         stopTaskCountRatio,
         scaleActionPeriodMillis,
         lagWeight,
@@ -372,7 +350,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
            ", taskCountMax=" + taskCountMax +
            ", taskCountMin=" + taskCountMin +
            ", taskCountStart=" + taskCountStart +
-           ", minTriggerScaleActionFrequencyMillis=" + 
minTriggerScaleActionFrequencyMillis +
            ", stopTaskCountRatio=" + stopTaskCountRatio +
            ", scaleActionPeriodMillis=" + scaleActionPeriodMillis +
            ", lagWeight=" + lagWeight +
@@ -397,7 +374,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
     private Integer taskCountMin;
     private Boolean enableTaskAutoScaler = true;
     private Integer taskCountStart;
-    private Long minTriggerScaleActionFrequencyMillis;
     private Double stopTaskCountRatio;
     private Long scaleActionPeriodMillis;
     private Double lagWeight;
@@ -438,12 +414,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
       return this;
     }
 
-    public Builder minTriggerScaleActionFrequencyMillis(long 
minTriggerScaleActionFrequencyMillis)
-    {
-      this.minTriggerScaleActionFrequencyMillis = 
minTriggerScaleActionFrequencyMillis;
-      return this;
-    }
-
     public Builder stopTaskCountRatio(Double stopTaskCountRatio)
     {
       this.stopTaskCountRatio = stopTaskCountRatio;
@@ -517,7 +487,6 @@ public class CostBasedAutoScalerConfig implements 
AutoScalerConfig
           taskCountMin,
           enableTaskAutoScaler,
           taskCountStart,
-          minTriggerScaleActionFrequencyMillis,
           stopTaskCountRatio,
           scaleActionPeriodMillis,
           lagWeight,
diff --git 
a/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
 
b/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
index 6d09221b410..45771d782ab 100644
--- 
a/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
+++ 
b/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerConfigTest.java
@@ -27,8 +27,8 @@ import org.junit.Test;
 
 import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.CostBasedAutoScalerConfig.DEFAULT_IDLE_WEIGHT;
 import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.CostBasedAutoScalerConfig.DEFAULT_LAG_WEIGHT;
-import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.CostBasedAutoScalerConfig.DEFAULT_MIN_SCALE_DELAY;
-import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.CostBasedAutoScalerConfig.DEFAULT_SCALE_ACTION_PERIOD_MILLIS;
+import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.CostBasedAutoScalerConfig.DEFAULT_MIN_SCALE_DOWN_DELAY;
+import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.CostBasedAutoScalerConfig.DEFAULT_MIN_SCALE_UP_DELAY;
 import static 
org.apache.druid.indexing.seekablestream.supervisor.autoscaler.WeightedCostFunction.OPTIMAL_TASK_IDLE_RATIO;
 
 @SuppressWarnings("TextBlockMigration")
@@ -99,13 +99,13 @@ public class CostBasedAutoScalerConfigTest
     Assert.assertEquals(2, config.getTaskCountMin());
 
     // Check defaults
-    Assert.assertEquals(DEFAULT_SCALE_ACTION_PERIOD_MILLIS, 
config.getScaleActionPeriodMillis());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_UP_DELAY.getMillis(), 
config.getScaleActionPeriodMillis());
     Assert.assertEquals(DEFAULT_LAG_WEIGHT, config.getLagWeight(), 0.001);
     Assert.assertEquals(DEFAULT_IDLE_WEIGHT, config.getIdleWeight(), 0.001);
     Assert.assertEquals(OPTIMAL_TASK_IDLE_RATIO, 
config.getOptimalTaskIdleRatio(), 0.001);
     // minScaleUpDelay and minScaleDownDelay each have their own independent 
default
-    Assert.assertEquals(Duration.millis(DEFAULT_SCALE_ACTION_PERIOD_MILLIS), 
config.getMinScaleUpDelay());
-    Assert.assertEquals(DEFAULT_MIN_SCALE_DELAY, 
config.getMinScaleDownDelay());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_UP_DELAY, 
config.getMinScaleUpDelay());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_DOWN_DELAY, 
config.getMinScaleDownDelay());
     Assert.assertFalse(config.isScaleDownOnTaskRolloverOnly());
     Assert.assertTrue(config.isUsePollIdleRatio());
     Assert.assertFalse(config.isUseTaskCountBoundariesOnScaleUp());
@@ -248,8 +248,8 @@ public class CostBasedAutoScalerConfigTest
                                                                   
.taskCountMax(10)
                                                                   
.taskCountMin(1)
                                                                   .build();
-    Assert.assertEquals(Duration.millis(DEFAULT_SCALE_ACTION_PERIOD_MILLIS), 
defaults.getMinScaleUpDelay());
-    Assert.assertEquals(DEFAULT_MIN_SCALE_DELAY, 
defaults.getMinScaleDownDelay());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_UP_DELAY, 
defaults.getMinScaleUpDelay());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_DOWN_DELAY, 
defaults.getMinScaleDownDelay());
 
     // Only minScaleUpDelay set: up uses explicit value, down uses its default
     CostBasedAutoScalerConfig upOnly = CostBasedAutoScalerConfig.builder()
@@ -258,7 +258,7 @@ public class CostBasedAutoScalerConfigTest
                                                                 
.minScaleUpDelay(Duration.standardMinutes(5))
                                                                 .build();
     Assert.assertEquals(Duration.standardMinutes(5), 
upOnly.getMinScaleUpDelay());
-    Assert.assertEquals(DEFAULT_MIN_SCALE_DELAY, 
upOnly.getMinScaleDownDelay());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_DOWN_DELAY, 
upOnly.getMinScaleDownDelay());
 
     // Only minScaleDownDelay set: down uses explicit value, up uses its own 
default (does not fall back to down)
     CostBasedAutoScalerConfig downOnly = CostBasedAutoScalerConfig.builder()
@@ -266,7 +266,7 @@ public class CostBasedAutoScalerConfigTest
                                                                   
.taskCountMin(1)
                                                                   
.minScaleDownDelay(Duration.standardMinutes(20))
                                                                   .build();
-    Assert.assertEquals(Duration.millis(DEFAULT_SCALE_ACTION_PERIOD_MILLIS), 
downOnly.getMinScaleUpDelay());
+    Assert.assertEquals(DEFAULT_MIN_SCALE_UP_DELAY, 
downOnly.getMinScaleUpDelay());
     Assert.assertEquals(Duration.standardMinutes(20), 
downOnly.getMinScaleDownDelay());
 
     // Both set: serde roundtrip preserves values
@@ -289,9 +289,9 @@ public class CostBasedAutoScalerConfigTest
   @SuppressWarnings("deprecation")
   public void testMinTriggerScaleActionFrequencyMillisSerdeCompat() throws 
Exception
   {
-    final long defaultMinTriggerMillis = DEFAULT_SCALE_ACTION_PERIOD_MILLIS;
-    final Duration defaultUp = 
Duration.millis(DEFAULT_SCALE_ACTION_PERIOD_MILLIS);
-    final Duration defaultDown = DEFAULT_MIN_SCALE_DELAY;
+    final long defaultMinTriggerMillis = -1;
+    final Duration defaultUp = DEFAULT_MIN_SCALE_UP_DELAY;
+    final Duration defaultDown = DEFAULT_MIN_SCALE_DOWN_DELAY;
 
     // Backwards-compat: nothing set -> everything uses its own default.
     {
@@ -313,8 +313,7 @@ public class CostBasedAutoScalerConfigTest
           + "\"minTriggerScaleActionFrequencyMillis\":900000}",
           CostBasedAutoScalerConfig.class
       );
-      Assert.assertEquals(900_000L, 
config.getMinTriggerScaleActionFrequencyMillis());
-      Assert.assertEquals(Duration.millis(900_000L), 
config.getMinScaleUpDelay());
+      Assert.assertEquals(defaultUp, config.getMinScaleUpDelay());
       Assert.assertEquals(defaultDown, config.getMinScaleDownDelay());
       assertRoundTrips(config);
     }
@@ -341,7 +340,6 @@ public class CostBasedAutoScalerConfigTest
           + "\"minScaleUpDelay\":\"PT2M\",\"minScaleDownDelay\":\"PT15M\"}",
           CostBasedAutoScalerConfig.class
       );
-      Assert.assertEquals(900_000L, 
config.getMinTriggerScaleActionFrequencyMillis());
       Assert.assertEquals(Duration.standardMinutes(2), 
config.getMinScaleUpDelay());
       Assert.assertEquals(Duration.standardMinutes(15), 
config.getMinScaleDownDelay());
       assertRoundTrips(config);
@@ -356,7 +354,6 @@ public class CostBasedAutoScalerConfigTest
           + "\"minScaleUpDelay\":\"PT2M\"}",
           CostBasedAutoScalerConfig.class
       );
-      Assert.assertEquals(900_000L, 
config.getMinTriggerScaleActionFrequencyMillis());
       Assert.assertEquals(Duration.standardMinutes(2), 
config.getMinScaleUpDelay());
       Assert.assertEquals(defaultDown, config.getMinScaleDownDelay());
       assertRoundTrips(config);
@@ -370,8 +367,7 @@ public class CostBasedAutoScalerConfigTest
           + "\"minScaleDownDelay\":\"PT15M\"}",
           CostBasedAutoScalerConfig.class
       );
-      Assert.assertEquals(900_000L, 
config.getMinTriggerScaleActionFrequencyMillis());
-      Assert.assertEquals(Duration.millis(900_000L), 
config.getMinScaleUpDelay());
+      Assert.assertEquals(defaultUp, config.getMinScaleUpDelay());
       Assert.assertEquals(Duration.standardMinutes(15), 
config.getMinScaleDownDelay());
       assertRoundTrips(config);
     }
diff --git 
a/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerTest.java
 
b/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerTest.java
index d773e20bfcb..435427fa37b 100644
--- 
a/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerTest.java
+++ 
b/indexing-service/src/test/java/org/apache/druid/indexing/seekablestream/supervisor/autoscaler/CostBasedAutoScalerTest.java
@@ -76,69 +76,51 @@ public class CostBasedAutoScalerTest
   }
 
   @Test
-  public void testComputeValidTaskCounts()
+  public void test_computeValidTaskCounts_returnsSortedArray()
   {
-    // For 100 partitions at 25 tasks (4 partitions/task), valid counts 
include 25 and 34
-    final int[] validTaskCounts = computeValidTaskCounts(
-        100,
-        25,
-        1,
-        100
+    final int partitionCount = 100;
+    final int minTaskCount = 1;
+    final int maxTaskCount = 100;
+    Assert.assertArrayEquals(
+        new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 25, 34, 
50, 100},
+        computeValidTaskCounts(partitionCount, minTaskCount, maxTaskCount)
     );
-    Assert.assertTrue("Expected current task count to be included", 
contains(validTaskCounts, 25));
-    Assert.assertTrue("Expected next scale-up option (34) to be included", 
contains(validTaskCounts, 34));
+  }
 
-    // Single partition
-    final int[] singlePartition = computeValidTaskCounts(
-        1,
-        1,
-        1,
-        100
+  @Test
+  public void test_computeValidTaskCounts_withSinglePartition()
+  {
+    final int partitionCount = 1;
+    final int minTaskCount = 1;
+    final int maxTaskCount = 100;
+    Assert.assertArrayEquals(
+        new int[]{1},
+        computeValidTaskCounts(partitionCount, minTaskCount, maxTaskCount)
     );
-    Assert.assertTrue("Single partition should yield at least one valid 
count", singlePartition.length > 0);
-    Assert.assertTrue("Single partition should include task count 1", 
contains(singlePartition, 1));
+  }
 
-    // Current exceeds partitions - should still yield valid, deduplicated 
options
-    final int[] exceedsPartitions = computeValidTaskCounts(
-        2,
-        5,
-        1,
-        100
+  @Test
+  public void test_computeValidTaskCounts_filtersByTaskCountMax()
+  {
+    final int partitionCount = 30;
+    final int taskCountMin = 1;
+    final int taskCountMax = 3;
+    Assert.assertArrayEquals(
+        new int[]{1, 2, 3},
+        computeValidTaskCounts(partitionCount, taskCountMin, taskCountMax)
     );
-    Assert.assertEquals(2, exceedsPartitions.length);
-    Assert.assertTrue(contains(exceedsPartitions, 1));
-    Assert.assertTrue(contains(exceedsPartitions, 2));
-
-    // Unbounded candidate generation includes both nearby and maximum task 
counts.
-    final int[] taskCounts = computeValidTaskCounts(30, 3, 1, 30);
-    Assert.assertTrue("Valid task counts should include max task count", 
contains(taskCounts, 30));
-    Assert.assertTrue("Valid task counts should include nearby scale-up task 
count", contains(taskCounts, 4));
+  }
 
-    // Respects taskCountMax
-    final int[] cappedCounts = computeValidTaskCounts(
-        30,
-        4,
-        1,
-        3
-    );
-    Assert.assertTrue("Should include taskCountMax when within bounds", 
contains(cappedCounts, 3));
-    Assert.assertFalse("Should not exceed taskCountMax", 
contains(cappedCounts, 4));
-
-    // Respects taskCountMin - filters out values below the minimum
-    // With partitionCount=100, currentTaskCount=10, the computed range 
includes values like 8, 9, 10, 12, 13
-    final int[] minCappedCounts = computeValidTaskCounts(100, 10, 10, 100);
-    Assert.assertFalse("Should not include values below taskCountMin (8)", 
contains(minCappedCounts, 8));
-    Assert.assertFalse("Should not include values below taskCountMin (9)", 
contains(minCappedCounts, 9));
-    Assert.assertTrue("Should include values at taskCountMin (10)", 
contains(minCappedCounts, 10));
-    Assert.assertTrue("Should include values above taskCountMin (12)", 
contains(minCappedCounts, 12));
-
-    // Both bounds applied together
-    final int[] bothBounds = computeValidTaskCounts(100, 10, 10, 12);
-    Assert.assertFalse("Should not include values below taskCountMin (8)", 
contains(bothBounds, 8));
-    Assert.assertFalse("Should not include values below taskCountMin (9)", 
contains(bothBounds, 9));
-    Assert.assertFalse("Should not include values above taskCountMax (13)", 
contains(bothBounds, 13));
-    Assert.assertTrue("Should include values at taskCountMin (10)", 
contains(bothBounds, 10));
-    Assert.assertTrue("Should include values at taskCountMax (12)", 
contains(bothBounds, 12));
+  @Test
+  public void 
test_computeValidTaskCounts_filtersByTaskCountMaxAndTaskCountMin()
+  {
+    final int partitionCount = 100;
+    final int taskCountMin = 10;
+    final int taskCountMax = 30;
+    Assert.assertArrayEquals(
+        new int[]{10, 12, 13, 15, 17, 20, 25},
+        computeValidTaskCounts(partitionCount, taskCountMin, taskCountMax)
+    );
   }
 
   @Test
@@ -512,7 +494,7 @@ public class CostBasedAutoScalerTest
                                                                          
.enableTaskAutoScaler(true)
                                                                          
.build();
     Assert.assertEquals(
-        CostBasedAutoScalerConfig.DEFAULT_MIN_SCALE_DELAY,
+        CostBasedAutoScalerConfig.DEFAULT_MIN_SCALE_DOWN_DELAY,
         cfgWithDefaults.getMinScaleDownDelay()
     );
     Assert.assertFalse(cfgWithDefaults.isScaleDownOnTaskRolloverOnly());
diff --git a/website/.spelling b/website/.spelling
index 468df62684f..e1723b254dc 100644
--- a/website/.spelling
+++ b/website/.spelling
@@ -907,8 +907,6 @@ c3.2xlarge
 defaultManualBrokerService
 maxPriority
 minPriority
-minScaleUpDelay
-minScaleDownDelay
 NUMBER_FEATURES
 NUMBER_OF_CONTRIBUTORS
 PreparedStatement


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

Reply via email to