AutoScalerPolicy extends AbstractPolicy { public static Builder builder() { return new Builder(); } AutoScalerPolicy(); @Deprecated  AutoScalerPolicy(Map<String,?> props); static Builder builder(); @Override void init(); @Override void rebind(); void setMetricLowerBound(Number val); void setMetricUpperBound(Number val); int getResizeUpIterationIncrement(); void setResizeUpIterationIncrement(Integer val); int getResizeDownIterationIncrement(); void setResizeDownIterationIncrement(Integer val); int getResizeUpIterationMax(); void setResizeUpIterationMax(Integer val); int getResizeDownIterationMax(); void setResizeDownIterationMax(Integer val); void setMinPeriodBetweenExecs(Duration val); void setResizeUpStabilizationDelay(Duration val); void setResizeDownStabilizationDelay(Duration val); void setMinPoolSize(int val); void setMaxPoolSize(int val); @Override void suspend(); @Override void resume(); @Override void setEntity(EntityLocal entity); @Override String toString(); static BasicNotificationSensor<Map> DEFAULT_POOL_HOT_SENSOR; static BasicNotificationSensor<Map> DEFAULT_POOL_COLD_SENSOR; static BasicNotificationSensor<Map> DEFAULT_POOL_OK_SENSOR; static BasicNotificationSensor<MaxPoolSizeReachedEvent> DEFAULT_MAX_SIZE_REACHED_SENSOR; static final String POOL_CURRENT_SIZE_KEY; static final String POOL_HIGH_THRESHOLD_KEY; static final String POOL_LOW_THRESHOLD_KEY; static final String POOL_CURRENT_WORKRATE_KEY; @CatalogConfig(label = "Metric")
    @SuppressWarnings("serial")
    @SetFromFlag("metric")
    static final ConfigKey<AttributeSensor<? extends Number>> METRIC; @SetFromFlag("entityWithMetric")
    static final ConfigKey<Entity> ENTITY_WITH_METRIC; @CatalogConfig(label = "Metric lower bound")
    @SetFromFlag("metricLowerBound")
    static final ConfigKey<Number> METRIC_LOWER_BOUND; @CatalogConfig(label = "Metric upper bound")
    @SetFromFlag("metricUpperBound")
    static final ConfigKey<Number> METRIC_UPPER_BOUND; @SetFromFlag("resizeUpIterationIncrement")
    static final ConfigKey<Integer> RESIZE_UP_ITERATION_INCREMENT; @SetFromFlag("resizeUpIterationMax")
    static final ConfigKey<Integer> RESIZE_UP_ITERATION_MAX; @SetFromFlag("resizeDownIterationIncrement")
    static final ConfigKey<Integer> RESIZE_DOWN_ITERATION_INCREMENT; @SetFromFlag("resizeDownIterationMax")
    static final ConfigKey<Integer> RESIZE_DOWN_ITERATION_MAX; @SetFromFlag("minPeriodBetweenExecs")
    static final ConfigKey<Duration> MIN_PERIOD_BETWEEN_EXECS; @SetFromFlag("resizeUpStabilizationDelay")
    static final ConfigKey<Duration> RESIZE_UP_STABILIZATION_DELAY; @SetFromFlag("resizeDownStabilizationDelay")
    static final ConfigKey<Duration> RESIZE_DOWN_STABILIZATION_DELAY; @SetFromFlag("minPoolSize")
    static final ConfigKey<Integer> MIN_POOL_SIZE; @SetFromFlag("maxPoolSize")
    static final ConfigKey<Integer> MAX_POOL_SIZE; static final ConfigKey<Integer> INSUFFICIENT_CAPACITY_HIGH_WATER_MARK; @SetFromFlag("resizeOperator")
    static final ConfigKey<ResizeOperator> RESIZE_OPERATOR; @SuppressWarnings("serial")
    @SetFromFlag("currentSizeOperator")
    static final ConfigKey<Function<Entity,Integer>> CURRENT_SIZE_OPERATOR; @SuppressWarnings("serial")
    @SetFromFlag("poolHotSensor")
    static final ConfigKey<BasicNotificationSensor<? extends Map>> POOL_HOT_SENSOR; @SuppressWarnings("serial")
    @SetFromFlag("poolColdSensor")
    static final ConfigKey<BasicNotificationSensor<? extends Map>> POOL_COLD_SENSOR; @SuppressWarnings("serial")
    @SetFromFlag("poolOkSensor")
    static final ConfigKey<BasicNotificationSensor<? extends Map>> POOL_OK_SENSOR; @SuppressWarnings("serial")
    @SetFromFlag("maxSizeReachedSensor")
    static final ConfigKey<BasicNotificationSensor<? super MaxPoolSizeReachedEvent>> MAX_SIZE_REACHED_SENSOR; @SetFromFlag("maxReachedNotificationDelay")
    static final ConfigKey<Duration> MAX_REACHED_NOTIFICATION_DELAY; }
@Test public void testHasId() throws Exception { resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .minPoolSize(2) .buildSpec()); Assert.assertTrue(policy.getId()!=null); }
@Test public void testNeverShrinkBelowMinimum() throws Exception { resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .minPoolSize(2) .buildSpec()); resizable.resize(4); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_COLD_SENSOR, message(4, 0L, 4*10L, 4*20L)); Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(resizable, 2)); }
@Test public void testNeverGrowAboveMaximmum() throws Exception { resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .maxPoolSize(5) .buildSpec()); resizable.resize(4); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, message(4, 1000000L, 4*10L, 4*20L)); Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(resizable, 5)); }
@Test public void testUsesResizeOperatorOverride() throws Exception { resizable.policies().remove(policy); final AtomicInteger counter = new AtomicInteger(); policy = resizable.policies().add(AutoScalerPolicy.builder() .resizeOperator(new ResizeOperator() { @Override public Integer resize(Entity entity, Integer desiredSize) { counter.incrementAndGet(); return desiredSize; }}) .buildSpec()); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, message(1, 21L, 1*10L, 1*20L)); Asserts.succeedsEventually(MutableMap.of("timeout",TIMEOUT_MS), new Runnable() { @Override public void run() { assertTrue(counter.get() >= 1, "cccounter="+counter); }}); }
@Test public void testUsesCustomSensorOverride() throws Exception { resizable.policies().remove(policy); @SuppressWarnings("rawtypes") BasicNotificationSensor<Map> customPoolHotSensor = new BasicNotificationSensor<Map>(Map.class, "custom.hot", ""); @SuppressWarnings("rawtypes") BasicNotificationSensor<Map> customPoolColdSensor = new BasicNotificationSensor<Map>(Map.class, "custom.cold", ""); @SuppressWarnings("rawtypes") BasicNotificationSensor<Map> customPoolOkSensor = new BasicNotificationSensor<Map>(Map.class, "custom.ok", ""); policy = resizable.policies().add(AutoScalerPolicy.builder() .poolHotSensor(customPoolHotSensor) .poolColdSensor(customPoolColdSensor) .poolOkSensor(customPoolOkSensor) .buildSpec()); resizable.sensors().emit(customPoolHotSensor, message(1, 21L, 1*10L, 1*20L)); Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(resizable, 2)); resizable.sensors().emit(customPoolColdSensor, message(2, 1L, 1*10L, 1*20L)); Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(resizable, 1)); }
@Test(groups="Integration") public void testResizeUpStabilizationDelayIgnoresBlip() throws Exception { long resizeUpStabilizationDelay = 1000L; Duration minPeriodBetweenExecs = Duration.ZERO; resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .resizeUpStabilizationDelay(Duration.of(resizeUpStabilizationDelay, TimeUnit.MILLISECONDS)) .minPeriodBetweenExecs(minPeriodBetweenExecs) .buildSpec()); resizable.resize(1); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, message(1, 61L, 1*10L, 1*20L)); Thread.sleep(resizeUpStabilizationDelay-OVERHEAD_DURATION_MS); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_OK_SENSOR, message(1, 11L, 4*10L, 4*20L)); assertEquals(resizable.getCurrentSize(), (Integer)1); Asserts.succeedsContinually(MutableMap.of("duration", 2000L), new Runnable() { @Override public void run() { assertEquals(resizable.getSizes(), ImmutableList.of(1)); }}); }
@Test(groups="Integration") public void testResizeUpStabilizationDelayTakesMaxSustainedDesired() throws Exception { long resizeUpStabilizationDelay = 1100L; Duration minPeriodBetweenExecs = Duration.ZERO; resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .resizeUpStabilizationDelay(Duration.of(resizeUpStabilizationDelay, TimeUnit.MILLISECONDS)) .minPeriodBetweenExecs(minPeriodBetweenExecs) .buildSpec()); resizable.resize(1); Stopwatch stopwatch = Stopwatch.createStarted(); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, message(1, 61L, 1*10L, 1*20L)); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, message(1, 21L, 1*10L, 1*20L)); Thread.sleep(resizeUpStabilizationDelay-OVERHEAD_DURATION_MS); long postSleepTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, message(1, 61L, 1*10L, 1*20L)); Asserts.succeedsEventually(MutableMap.of("period", 1, "timeout", TIMEOUT_MS), new Runnable() { @Override public void run() { assertTrue(resizable.getCurrentSize() >= 2, "currentSize="+resizable.getCurrentSize()); }}); assertEquals(resizable.getCurrentSize(), (Integer)2, stopwatch.elapsed(TimeUnit.MILLISECONDS)+"ms after first emission; "+(stopwatch.elapsed(TimeUnit.MILLISECONDS)-postSleepTime)+"ms after last"); long timeToResizeTo2 = stopwatch.elapsed(TimeUnit.MILLISECONDS); assertTrue(timeToResizeTo2 >= resizeUpStabilizationDelay-EARLY_RETURN_MS && timeToResizeTo2 <= resizeUpStabilizationDelay+OVERHEAD_DURATION_MS, "Resizing to 2: time="+timeToResizeTo2+"; resizeUpStabilizationDelay="+resizeUpStabilizationDelay); Asserts.succeedsEventually(MutableMap.of("period", 1, "timeout", TIMEOUT_MS), currentSizeAsserter(resizable, 4)); long timeToResizeTo4 = stopwatch.elapsed(TimeUnit.MILLISECONDS) - postSleepTime; assertTrue(timeToResizeTo4 >= resizeUpStabilizationDelay-EARLY_RETURN_MS && timeToResizeTo4 <= resizeUpStabilizationDelay+OVERHEAD_DURATION_MS, "Resizing to 4: timeToResizeTo4="+timeToResizeTo4+"; timeToResizeTo2="+timeToResizeTo2+"; resizeUpStabilizationDelay="+resizeUpStabilizationDelay); }
@Test(groups="Integration") public void testResizeUpStabilizationDelayResizesAfterDelay() { final long resizeUpStabilizationDelay = 1000L; Duration minPeriodBetweenExecs = Duration.ZERO; resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .resizeUpStabilizationDelay(Duration.of(resizeUpStabilizationDelay, TimeUnit.MILLISECONDS)) .minPeriodBetweenExecs(minPeriodBetweenExecs) .buildSpec()); resizable.resize(1); final long emitTime = System.currentTimeMillis(); final Map<String, Object> need4 = message(1, 61L, 1*10L, 1*20L); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, need4); final AtomicInteger emitCount = new AtomicInteger(0); Asserts.succeedsEventually(MutableMap.of("timeout", TIMEOUT_MS), new Runnable() { @Override public void run() { if (System.currentTimeMillis() - emitTime > (2+emitCount.get())*resizeUpStabilizationDelay) { resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_HOT_SENSOR, need4); emitCount.incrementAndGet(); } assertEquals(resizable.getCurrentSize(), (Integer)4); }}); long resizeDelay = System.currentTimeMillis() - emitTime; assertTrue(resizeDelay >= (resizeUpStabilizationDelay-EARLY_RETURN_MS), "resizeDelay="+resizeDelay); }
@Test(groups="Integration") public void testResizeDownStabilizationDelayIgnoresBlip() throws Exception { long resizeStabilizationDelay = 1000L; Duration minPeriodBetweenExecs = Duration.ZERO; resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .resizeDownStabilizationDelay(Duration.of(resizeStabilizationDelay, TimeUnit.MILLISECONDS)) .minPeriodBetweenExecs(minPeriodBetweenExecs) .buildSpec()); resizable.resize(2); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_COLD_SENSOR, message(2, 1L, 2*10L, 2*20L)); Thread.sleep(resizeStabilizationDelay-OVERHEAD_DURATION_MS); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_OK_SENSOR, message(2, 20L, 1*10L, 1*20L)); assertEquals(resizable.getCurrentSize(), (Integer)2); Asserts.succeedsContinually(MutableMap.of("duration", 2000L), new Runnable() { @Override public void run() { assertEquals(resizable.getSizes(), ImmutableList.of(2)); }}); }
@Test(groups="Integration") public void testResizeDownStabilizationDelayResizesAfterDelay() throws Exception { final long resizeDownStabilizationDelay = 1000L; Duration minPeriodBetweenExecs = Duration.ZERO; resizable.policies().remove(policy); policy = resizable.policies().add(AutoScalerPolicy.builder() .resizeDownStabilizationDelay(Duration.of(resizeDownStabilizationDelay, TimeUnit.MILLISECONDS)) .minPeriodBetweenExecs(minPeriodBetweenExecs) .buildSpec()); resizable.resize(2); final long emitTime = System.currentTimeMillis(); final Map<String, Object> needJust1 = message(2, 1L, 2*10L, 2*20L); resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_COLD_SENSOR, needJust1); final AtomicInteger emitCount = new AtomicInteger(0); Asserts.succeedsEventually(MutableMap.of("timeout", TIMEOUT_MS), new Runnable() { @Override public void run() { if (System.currentTimeMillis() - emitTime > (2+emitCount.get())*resizeDownStabilizationDelay) { resizable.sensors().emit(AutoScalerPolicy.DEFAULT_POOL_COLD_SENSOR, needJust1); emitCount.incrementAndGet(); } assertEquals(resizable.getCurrentSize(), (Integer)1); }}); long resizeDelay = System.currentTimeMillis() - emitTime; assertTrue(resizeDelay >= (resizeDownStabilizationDelay-EARLY_RETURN_MS), "resizeDelay="+resizeDelay); }