From 812f112e36d51a242ff1c8d0ba2a91aa15249910 Mon Sep 17 00:00:00 2001 From: zero88 Date: Thu, 14 Dec 2023 18:47:47 +0700 Subject: [PATCH] refactor: Add DefaultOptions to override some global property by `System.property` --- .../zero88/schedulerx/DefaultOptions.java | 99 +++++++++++++++++++ .../zero88/schedulerx/TimeoutPolicy.java | 18 +--- .../schedulerx/trigger/PreviewParameter.java | 7 +- .../schedulerx/trigger/rule/TriggerRule.java | 21 ++-- .../trigger/rule/TriggerRuleImpl.java | 8 +- .../zero88/schedulerx/DefaultOptionsTest.java | 48 +++++++++ 6 files changed, 170 insertions(+), 31 deletions(-) create mode 100644 core/src/main/java/io/github/zero88/schedulerx/DefaultOptions.java create mode 100644 core/src/test/java/io/github/zero88/schedulerx/DefaultOptionsTest.java diff --git a/core/src/main/java/io/github/zero88/schedulerx/DefaultOptions.java b/core/src/main/java/io/github/zero88/schedulerx/DefaultOptions.java new file mode 100644 index 0000000..716951b --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/DefaultOptions.java @@ -0,0 +1,99 @@ +package io.github.zero88.schedulerx; + +import java.time.Duration; +import java.time.format.DateTimeParseException; + +import io.github.zero88.schedulerx.impl.Utils; +import io.github.zero88.schedulerx.trigger.Trigger; +import io.vertx.core.VertxOptions; + +/** + * Instances of this class are used to configure the default options for {@link Trigger}, and {@link Task} instances. + * + * @since 2.0.0 + */ +public final class DefaultOptions { + + public static final String DEFAULT_MAX_EXECUTION_TIMEOUT = "schedulerx.default_max_execution_timeout"; + public static final String DEFAULT_MAX_EVALUATION_TIMEOUT = "schedulerx.default_max_evaluation_timeout"; + public static final String DEFAULT_MAX_TRIGGER_RULE_LEEWAY = "schedulerx.default_max_trigger_rule_leeway"; + public static final String DEFAULT_MAX_TRIGGER_PREVIEW_COUNT = "schedulerx.default_max_trigger_preview_count"; + + + private static class Holder { + + private static final DefaultOptions INSTANCE = new DefaultOptions(); + + } + + public static DefaultOptions getInstance() { + return DefaultOptions.Holder.INSTANCE; + } + + /** + * Declares the default max execution timeout. + * + * @apiNote It can be overridden by system property with key {@link #DEFAULT_MAX_EXECUTION_TIMEOUT} + */ + public final Duration maxExecutionTimeout; + /** + * Declares the default max trigger evaluation timeout. + * + * @apiNote It can be overridden by system property with key {@link #DEFAULT_MAX_EVALUATION_TIMEOUT} + */ + public final Duration maxEvaluationTimeout; + /** + * Declares the default max trigger rule leeway time. + * + * @apiNote It can be overridden by system property with key {@link #DEFAULT_MAX_TRIGGER_RULE_LEEWAY} + */ + public final Duration maxTriggerRuleLeeway; + /** + * Declares the default max number of the trigger preview items. + * + * @apiNote It can be overridden by system property with key {@link #DEFAULT_MAX_TRIGGER_PREVIEW_COUNT} + */ + public final int maxTriggerPreviewCount; + + DefaultOptions() { + this.maxExecutionTimeout = loadMaxExecutionTimeout(); + this.maxEvaluationTimeout = loadMaxEvaluationTimeout(); + this.maxTriggerRuleLeeway = loadTriggerRuleLeeway(); + this.maxTriggerPreviewCount = loadTriggerPreviewCount(); + } + + private static Duration loadMaxExecutionTimeout() { + try { + return Duration.parse(System.getProperty(DEFAULT_MAX_EXECUTION_TIMEOUT)); + } catch (DateTimeParseException | NullPointerException ex) { + return Duration.of(VertxOptions.DEFAULT_MAX_WORKER_EXECUTE_TIME, + Utils.toChronoUnit(VertxOptions.DEFAULT_MAX_WORKER_EXECUTE_TIME_UNIT)); + } + } + + private static Duration loadMaxEvaluationTimeout() { + try { + return Duration.parse(System.getProperty(DEFAULT_MAX_EVALUATION_TIMEOUT)); + } catch (DateTimeParseException | NullPointerException ex) { + return Duration.of(VertxOptions.DEFAULT_MAX_EVENT_LOOP_EXECUTE_TIME, + Utils.toChronoUnit(VertxOptions.DEFAULT_MAX_EVENT_LOOP_EXECUTE_TIME_UNIT)); + } + } + + private static Duration loadTriggerRuleLeeway() { + try { + return Duration.parse(System.getProperty(DEFAULT_MAX_TRIGGER_RULE_LEEWAY)); + } catch (DateTimeParseException | NullPointerException ex) { + return Duration.ofSeconds(10); + } + } + + private static int loadTriggerPreviewCount() { + try { + return Integer.parseInt(System.getProperty(DEFAULT_MAX_TRIGGER_PREVIEW_COUNT)); + } catch (NumberFormatException | NullPointerException ex) { + return 30; + } + } + +} diff --git a/core/src/main/java/io/github/zero88/schedulerx/TimeoutPolicy.java b/core/src/main/java/io/github/zero88/schedulerx/TimeoutPolicy.java index c289aba..73268f3 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TimeoutPolicy.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TimeoutPolicy.java @@ -6,9 +6,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import io.github.zero88.schedulerx.impl.Utils; -import io.vertx.core.VertxOptions; - import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -40,19 +37,12 @@ public static TimeoutPolicy create(@JsonProperty("evaluationTimeout") @Nullable } return duration; }; - final Duration evTimeout = check.apply(evaluationTimeout, - Duration.of(VertxOptions.DEFAULT_MAX_EVENT_LOOP_EXECUTE_TIME, - Utils.toChronoUnit( - VertxOptions.DEFAULT_MAX_EVENT_LOOP_EXECUTE_TIME_UNIT))); - final Duration exeTimeout = check.apply(executionTimeout, - Duration.of(VertxOptions.DEFAULT_MAX_WORKER_EXECUTE_TIME, - Utils.toChronoUnit( - VertxOptions.DEFAULT_MAX_WORKER_EXECUTE_TIME_UNIT))); - return new TimeoutPolicy(evTimeout, exeTimeout); + return new TimeoutPolicy(check.apply(evaluationTimeout, DefaultOptions.getInstance().maxEvaluationTimeout), + check.apply(executionTimeout, DefaultOptions.getInstance().maxExecutionTimeout)); } /** - * Declares the evaluation timeout. + * Declares the evaluation timeout. Default is {@link DefaultOptions#maxEvaluationTimeout} * * @return the evaluation timeout * @since 2.0.0 @@ -61,7 +51,7 @@ public static TimeoutPolicy create(@JsonProperty("evaluationTimeout") @Nullable public @NotNull Duration evaluationTimeout() { return evaluationTimeout; } /** - * Declares the execution timeout. + * Declares the execution timeout. Default is {@link DefaultOptions#maxExecutionTimeout} * * @return the execution timeout * @since 2.0.0 diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/PreviewParameter.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/PreviewParameter.java index 64a1d9d..8c88958 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/PreviewParameter.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/PreviewParameter.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import io.github.zero88.schedulerx.DefaultOptions; import io.github.zero88.schedulerx.trigger.rule.TriggerRule; /** @@ -18,8 +19,6 @@ */ public final class PreviewParameter { - public static final int MAX_TIMES = 30; - private int times; private Instant startedAt = Instant.now(); private ZoneId timeZone; @@ -55,10 +54,10 @@ public static PreviewParameter byDefault() { } /** - * @return the number of a preview item, maximum is {@link #MAX_TIMES} + * @return the number of a preview item, maximum is {@link DefaultOptions#maxTriggerPreviewCount} */ public int getTimes() { - return Math.max(1, Math.min(times, MAX_TIMES)); + return Math.max(1, Math.min(times, DefaultOptions.getInstance().maxTriggerPreviewCount)); } /** diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRule.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRule.java index 6f579a3..1b9e3cb 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRule.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRule.java @@ -7,6 +7,8 @@ import org.jetbrains.annotations.NotNull; +import io.github.zero88.schedulerx.DefaultOptions; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; @@ -19,11 +21,6 @@ @SuppressWarnings("rawtypes") public interface TriggerRule { - /** - * A maximum of leeway time - */ - Duration MAX_LEEWAY = Duration.ofSeconds(30); - /** * A no-op trigger rule. */ @@ -47,7 +44,14 @@ public interface TriggerRule { Instant until(); /** - * Declares the allowable margin of time in the time validation of {@link #satisfy(Instant)} and {@link #until()} + * Declares the allowable margin of time in the time validation of {@link #satisfy(Instant)} and {@link #until()}. + *

+ * The leeway time has constraints: + *

* * @return the leeway time */ @@ -86,12 +90,11 @@ default boolean isExceeded(@NotNull Instant firedAt) { return create(timeframes, null, null); } - /** * Create a new trigger rule * * @param timeframes the given timeframes - * @param leeway the given leeway + * @param leeway the given leeway * @return a new Trigger rule */ static @NotNull TriggerRule create(List timeframes, Duration leeway) { @@ -111,7 +114,7 @@ default boolean isExceeded(@NotNull Instant firedAt) { /** * Create a new trigger rule * - * @param until the given until + * @param until the given until * @param leeway the given leeway * @return a new Trigger rule */ diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRuleImpl.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRuleImpl.java index e018571..fdf8b8d 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRuleImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/rule/TriggerRuleImpl.java @@ -9,6 +9,8 @@ import org.jetbrains.annotations.NotNull; +import io.github.zero88.schedulerx.DefaultOptions; + @SuppressWarnings("rawtypes") final class TriggerRuleImpl implements TriggerRule { @@ -65,13 +67,11 @@ private int computeHashCode() { @NotNull private static Duration validateLeewayTime(Duration leeway) { final Duration given = Optional.ofNullable(leeway).orElse(Duration.ZERO); - if (given.compareTo(MAX_LEEWAY) > 0) { - return MAX_LEEWAY; - } if (given.isNegative()) { return Duration.ZERO; } - return given; + final Duration maxLeeway = DefaultOptions.getInstance().maxTriggerRuleLeeway; + return given.compareTo(maxLeeway) > 0 ? maxLeeway : given; } } diff --git a/core/src/test/java/io/github/zero88/schedulerx/DefaultOptionsTest.java b/core/src/test/java/io/github/zero88/schedulerx/DefaultOptionsTest.java new file mode 100644 index 0000000..45c9c1e --- /dev/null +++ b/core/src/test/java/io/github/zero88/schedulerx/DefaultOptionsTest.java @@ -0,0 +1,48 @@ +package io.github.zero88.schedulerx; + +import java.time.Duration; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junitpioneer.jupiter.SetSystemProperty; + +@Execution(ExecutionMode.SAME_THREAD) +class DefaultOptionsTest { + + @Test + void test_default_options() { + Assertions.assertEquals(DefaultOptions.getInstance().maxEvaluationTimeout, Duration.ofSeconds(2)); + Assertions.assertEquals(DefaultOptions.getInstance().maxExecutionTimeout, Duration.ofSeconds(60)); + Assertions.assertEquals(DefaultOptions.getInstance().maxTriggerPreviewCount, 30); + Assertions.assertEquals(DefaultOptions.getInstance().maxTriggerRuleLeeway, Duration.ofSeconds(10)); + } + + + @Test + @SetSystemProperty(key = "schedulerx.default_max_evaluation_timeout", value = "PT1S") + void test_override_max_evaluation_timeout() { + Assertions.assertEquals(new DefaultOptions().maxEvaluationTimeout, Duration.ofSeconds(1)); + } + + @Test + @SetSystemProperty(key = "schedulerx.default_max_execution_timeout", value = "PT10M") + void test_override_max_execution_timeout() { + Assertions.assertEquals(new DefaultOptions().maxExecutionTimeout, Duration.ofMinutes(10)); + } + + @Test + @SetSystemProperty(key = "schedulerx.default_max_trigger_preview_count", value = "12") + void test_override_max_preview_count() { + Assertions.assertEquals(new DefaultOptions().maxTriggerPreviewCount, 12); + } + + + @Test + @SetSystemProperty(key = "schedulerx.default_max_trigger_rule_leeway", value = "PT3S") + void test_override_max_trigger_rule_leeway() { + Assertions.assertEquals(new DefaultOptions().maxTriggerRuleLeeway, Duration.ofSeconds(3)); + } + +}