From 1751306de009b4bfaf5ca9a84741474b71a823ab Mon Sep 17 00:00:00 2001 From: zero88 Date: Wed, 26 Jul 2023 11:40:43 +0700 Subject: [PATCH 1/5] feat(#48): Upgrade vertx and lib dependencies feat(#48): Use internal vertx logger --- buildSrc/src/main/kotlin/Dependencies.kt | 33 +++++++++---------- core/build.gradle.kts | 15 +++------ .../schedulerx/TaskExecutorLogMonitor.java | 24 +++++++------- .../schedulerx/TaskExecutorMonitor.java | 2 +- .../schedulerx/impl/AbstractTaskExecutor.java | 11 ++++--- 5 files changed, 39 insertions(+), 46 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index f631126..7e6be2d 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -1,4 +1,4 @@ -private fun Map>.ver(minor: Int, patch: Int):String = "${minor}.${this[minor]?.get(patch)}" +private fun Map>.ver(minor: Int, patch: Int): String = "${minor}.${this[minor]?.get(patch)}" object PlayioPlugin { @@ -25,6 +25,16 @@ object UtilLibs { const val jetbrainsAnnotations = "org.jetbrains:annotations:${Version.jetbrainsAnnotations}" } +object LogLibs { + + object Version { + + const val logback = "1.4.8" + } + + const val logback = "ch.qos.logback:logback-classic:${Version.logback}" +} + object JacksonLibs { object Version { @@ -34,7 +44,6 @@ object JacksonLibs { const val annotations = "com.fasterxml.jackson.core:jackson-annotations:${Version.jackson}" const val databind = "com.fasterxml.jackson.core:jackson-databind:${Version.jackson}" - const val datetime = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${Version.jackson}" } object TestLibs { @@ -55,22 +64,10 @@ object VertxLibs { object Version { - private val pool = mapOf(2 to (0..7).toList(), 3 to (0..6).toList(), 4 to (0..0).toList()) - @JvmField val vertxCore = "4.${pool.ver(3, 5)}" - @JvmField val vertxSQL = "4.${pool.ver(3, 5)}" - const val vertxJunit = "4.2.5" - } - - @JvmField val core = "io.vertx:vertx-core:${Version.vertxCore}" - @JvmField val junit5 = "io.vertx:vertx-junit5:${Version.vertxJunit}" -} - -object ValidationLibs { - object Version { - const val api = "3.0.2" - const val hibernate = "8.0.0.Final" + private val pool = mapOf(2 to (0..7).toList(), 3 to (0..6).toList(), 4 to (0..4).toList()) + @JvmField val defaultVersion = "4.${pool.ver(4, 4)}" } - const val api = "jakarta.validation:jakarta.validation-api:${Version.api}" - const val hibernate = "org.hibernate.validator:hibernate-validator:${Version.hibernate}" + @JvmField val core = "io.vertx:vertx-core:${Version.defaultVersion}" + @JvmField val junit5 = "io.vertx:vertx-junit5:${Version.defaultVersion}" } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 0fbb472..ee2bfc6 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -7,28 +7,21 @@ oss { baseName.set("schedulerx") title.set("Scheduler.x") } -val vertxVersion = "4.0.0" -val vertxCore = "io.vertx:vertx-core:${vertxVersion}" -val vertx5Junit = "io.vertx:vertx-junit5:${vertxVersion}" dependencies { - api(vertxCore) - api("org.slf4j:slf4j-api:1.7.30") + api(VertxLibs.core) + compileOnly(JacksonLibs.annotations) compileOnly(JacksonLibs.databind) compileOnly(UtilLibs.jetbrainsAnnotations) - annotationProcessor(UtilLibs.jetbrainsAnnotations) - testImplementation(vertx5Junit) testImplementation(TestLibs.junit5Params) testImplementation(JacksonLibs.databind) - testImplementation("ch.qos.logback:logback-classic:1.2.3") + testImplementation(LogLibs.logback) testCompileOnly(UtilLibs.jetbrainsAnnotations) - testAnnotationProcessor(UtilLibs.jetbrainsAnnotations) testFixturesApi(TestLibs.junit5Api) testFixturesApi(TestLibs.junit5Engine) testFixturesApi(TestLibs.junit5Vintage) - testFixturesApi(vertx5Junit) + testFixturesApi(VertxLibs.junit5) testFixturesCompileOnly(UtilLibs.jetbrainsAnnotations) - testFixturesAnnotationProcessor(UtilLibs.jetbrainsAnnotations) } diff --git a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorLogMonitor.java b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorLogMonitor.java index 80bd0af..e7d5f9f 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorLogMonitor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorLogMonitor.java @@ -1,47 +1,49 @@ package io.github.zero88.schedulerx; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + +import io.vertx.core.impl.logging.Logger; +import io.vertx.core.impl.logging.LoggerFactory; /** - * Represents for log monitor + * Represents for a log monitor that observes and do log on each lifecycle event of the task executor. * * @since 1.0.0 */ public interface TaskExecutorLogMonitor extends TaskExecutorMonitor { Logger LOGGER = LoggerFactory.getLogger(TaskExecutorLogMonitor.class); - TaskExecutorMonitor LOG_MONITOR = new TaskExecutorLogMonitor() {}; + TaskExecutorLogMonitor LOG_MONITOR = new TaskExecutorLogMonitor() { }; @Override default void onUnableSchedule(@NotNull TaskResult result) { - LOGGER.error("Unable schedule task at [{}] due to error", result.unscheduledAt(), result.error()); + LOGGER.error("Unable schedule task at [" + result.unscheduledAt() + "] due to error", result.error()); } @Override default void onSchedule(@NotNull TaskResult result) { if (result.isReschedule()) { - LOGGER.debug("TaskExecutor is rescheduled at [{}] round [{}]", result.rescheduledAt(), result.round()); + LOGGER.debug( + "TaskExecutor is rescheduled at [" + result.rescheduledAt() + "] round [" + result.round() + "]"); } else { - LOGGER.debug("TaskExecutor is available at [{}]", result.availableAt()); + LOGGER.debug("TaskExecutor is available at [" + result.availableAt() + "]"); } } @Override default void onMisfire(@NotNull TaskResult result) { - LOGGER.debug("Misfire tick [{}] at [{}]", result.tick(), result.triggeredAt()); + LOGGER.debug("Misfire tick [" + result.tick() + "] at [" + result.triggeredAt() + "]"); } @Override default void onEach(@NotNull TaskResult result) { - LOGGER.debug("Finish round [{}] - Is Error [{}] | Executed at [{}] - Finished at [{}]", result.round(), - result.isError(), result.executedAt(), result.finishedAt()); + LOGGER.debug("Finish round [" + result.round() + "] - Is Error [" + result.isError() + "] | Executed at [" + + result.executedAt() + "] - Finished at [" + result.finishedAt() + "]"); } @Override default void onCompleted(@NotNull TaskResult result) { - LOGGER.debug("Completed task in round [{}] at [{}]", result.round(), result.completedAt()); + LOGGER.debug("Completed task in round [" + result.round() + "] at [" + result.completedAt() + "]"); } } diff --git a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java index e5cb592..2a30c83 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java @@ -3,7 +3,7 @@ import org.jetbrains.annotations.NotNull; /** - * Represents for monitor that watches lifecycle event in executor + * Represents for a monitor that watches lifecycle event in executor * * @see TaskResult * @since 1.0.0 diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java index b186453..6b732fc 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java @@ -3,8 +3,6 @@ import java.time.Instant; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import io.github.zero88.schedulerx.JobData; import io.github.zero88.schedulerx.Task; @@ -20,9 +18,12 @@ import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.WorkerExecutor; +import io.vertx.core.impl.logging.Logger; +import io.vertx.core.impl.logging.LoggerFactory; public abstract class AbstractTaskExecutor implements TriggerTaskExecutor { + @SuppressWarnings("java:S3416") protected static final Logger LOGGER = LoggerFactory.getLogger(TaskExecutor.class); @NotNull private final Vertx vertx; @@ -110,7 +111,7 @@ public void cancel() { protected void debug(long tick, long round, @NotNull Instant at, @NotNull String event) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("TaskExecutor[{}][{}][{}]::{}", tick, round, at, event); + LOGGER.debug("TaskExecutor[" + tick + "][" + round + "][" + at + "]::" + event); } } @@ -169,8 +170,8 @@ protected void onResult(@NotNull AsyncResult asyncResult) { state.markIdle(); final Instant finishedAt = Instant.now(); if (asyncResult.failed()) { - LOGGER.warn("TaskExecutor[{}][{}][{}]::{}", state().tick(), state().round(), finishedAt, - "Internal execution error", asyncResult.cause()); + LOGGER.warn("TaskExecutor[" + state().tick() + "][" + state().round() + "][" + finishedAt + "]" + + "::Internal execution error", asyncResult.cause()); } if (asyncResult.succeeded()) { final TaskExecutionContextInternal result = (TaskExecutionContextInternal) asyncResult.result(); From 73f67abdcfa2d141a4f014461db5306cb58130c1 Mon Sep 17 00:00:00 2001 From: zero88 Date: Wed, 26 Jul 2023 11:41:26 +0700 Subject: [PATCH 2/5] feat(#48): Consistent builder pattern in testFixtures --- .../schedulerx/CronTaskExecutorTest.java | 6 +- .../schedulerx/IntervalTaskExecutorTest.java | 17 ++- .../schedulerx/custom/HttpClientTaskTest.java | 4 +- .../schedulerx/TaskExecutorAsserter.java | 114 +++++++++++++++--- 4 files changed, 113 insertions(+), 28 deletions(-) diff --git a/core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java b/core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java index 42a387e..7c5d3af 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java +++ b/core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java @@ -55,9 +55,9 @@ void test_run_task_by_cron(Vertx vertx, VertxTestContext testContext) { } }) .setMonitor(TaskExecutorAsserter.builder() - .testContext(testContext) - .schedule(schedule) - .completed(completed) + .setTestContext(testContext) + .setSchedule(schedule) + .setCompleted(completed) .build()) .build() .start(); diff --git a/core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java b/core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java index 4478d39..902a29e 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java +++ b/core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java @@ -69,8 +69,11 @@ void test_run_task_after_delay(Vertx vertx, VertxTestContext ctx) { .setVertx(vertx) .setTrigger(IntervalTrigger.builder().initialDelay(2).interval(2).repeat(2).build()) .setTask((jobData, context) -> { }) - .setMonitor( - TaskExecutorAsserter.builder().testContext(ctx).schedule(s).completed(c).build()) + .setMonitor(TaskExecutorAsserter.builder() + .setTestContext(ctx) + .setSchedule(s) + .setCompleted(c) + .build()) .build() .start(worker); } @@ -92,7 +95,8 @@ void test_run_blocking_task_in_the_end(Vertx vertx, VertxTestContext testContext sleep(3000, testContext); checkpoint.flag(); }) - .setMonitor(TaskExecutorAsserter.builder().testContext(testContext).completed(c).build()) + .setMonitor( + TaskExecutorAsserter.builder().setTestContext(testContext).setCompleted(c).build()) .build() .start(worker); } @@ -135,8 +139,11 @@ void test_cancel_task_in_condition(Vertx vertx, VertxTestContext context) { .setVertx(vertx) .setTrigger(IntervalTrigger.builder().interval(1).repeat(10).build()) .setTask(task) - .setMonitor( - TaskExecutorAsserter.builder().testContext(context).each(e).completed(c).build()) + .setMonitor(TaskExecutorAsserter.builder() + .setTestContext(context) + .setEach(e) + .setCompleted(c) + .build()) .build() .start(); } diff --git a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java index dd96663..d2dcf16 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java +++ b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java @@ -32,8 +32,8 @@ void test_http_task(Vertx vertx, VertxTestContext testContext) { Assertions.assertEquals("http://" + host + path, response.getJsonObject("response").getString("url")); }; final TaskExecutorAsserter monitor = TaskExecutorAsserter.builder() - .testContext(testContext) - .each(verification) + .setTestContext(testContext) + .setEach(verification) .build(); IntervalTaskExecutor.builder() .setVertx(vertx) diff --git a/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java b/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java index fde9f2c..39c0a84 100644 --- a/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java +++ b/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java @@ -1,28 +1,39 @@ package io.github.zero88.schedulerx; import java.util.Objects; +import java.util.Optional; import java.util.function.Consumer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Assertions; import io.vertx.junit5.Checkpoint; import io.vertx.junit5.VertxTestContext; -public class TaskExecutorAsserter implements TaskExecutorLogMonitor { +/** + * Represents for the executor monitor that able to do test assert. + * + * @see TaskExecutorMonitor + * @since 1.0.0 + */ +public final class TaskExecutorAsserter implements TaskExecutorMonitor { @NotNull private final VertxTestContext testContext; + @NotNull + private final TaskExecutorMonitor logMonitor; private final Consumer unableSchedule; private final Consumer schedule; private final Consumer misfire; private final Consumer each; private final Consumer completed; - TaskExecutorAsserter(@NotNull VertxTestContext testContext, Consumer unableSchedule, - Consumer schedule, Consumer misfire, Consumer each, - Consumer completed) { + TaskExecutorAsserter(@NotNull VertxTestContext testContext, @Nullable TaskExecutorMonitor logMonitor, + Consumer unableSchedule, Consumer schedule, + Consumer misfire, Consumer each, Consumer completed) { this.testContext = Objects.requireNonNull(testContext, "Vertx Test context is required"); + this.logMonitor = Optional.ofNullable(logMonitor).orElse(TaskExecutorLogMonitor.LOG_MONITOR); this.unableSchedule = unableSchedule; this.schedule = schedule; this.misfire = misfire; @@ -34,31 +45,31 @@ public class TaskExecutorAsserter implements TaskExecutorLogMonitor { @Override public void onUnableSchedule(@NotNull TaskResult result) { - TaskExecutorLogMonitor.super.onUnableSchedule(result); + logMonitor.onUnableSchedule(result); verify(result, unableSchedule); } @Override public void onSchedule(@NotNull TaskResult result) { - TaskExecutorLogMonitor.super.onSchedule(result); + logMonitor.onSchedule(result); verify(result, schedule); } @Override public void onMisfire(@NotNull TaskResult result) { - TaskExecutorLogMonitor.super.onMisfire(result); + logMonitor.onMisfire(result); verify(result, misfire); } @Override public void onEach(@NotNull TaskResult result) { - TaskExecutorLogMonitor.super.onEach(result); + logMonitor.onEach(result); verify(result, each); } @Override public void onCompleted(@NotNull TaskResult result) { - TaskExecutorLogMonitor.super.onCompleted(result); + logMonitor.onCompleted(result); verify(result, r -> { completed.accept(r); testContext.completeNow(); @@ -75,8 +86,9 @@ private void verify(@NotNull TaskResult result, Consumer verificatio } } + @SuppressWarnings("java:S5960") static TaskExecutorMonitor unableScheduleAsserter(VertxTestContext testContext, Checkpoint checkpoint) { - return TaskExecutorAsserter.builder().testContext(testContext).unableSchedule(result -> { + return TaskExecutorAsserter.builder().setTestContext(testContext).setUnableSchedule(result -> { checkpoint.flag(); Assertions.assertNotNull(result.unscheduledAt()); Assertions.assertNull(result.availableAt()); @@ -88,45 +100,111 @@ static TaskExecutorMonitor unableScheduleAsserter(VertxTestContext testContext, public static class TaskExecutorAsserterBuilder { private VertxTestContext testContext; + private TaskExecutorMonitor logMonitor; private Consumer unableSchedule; private Consumer schedule; private Consumer misfire; private Consumer each; private Consumer completed; - public TaskExecutorAsserterBuilder testContext(@NotNull VertxTestContext testContext) { + /** + * Set Vertx test context + * + * @param testContext test context + * @return this for fluent API + * @see VertxTestContext + */ + public TaskExecutorAsserterBuilder setTestContext(@NotNull VertxTestContext testContext) { this.testContext = testContext; return this; } - public TaskExecutorAsserterBuilder unableSchedule(Consumer unableSchedule) { + /** + * Set log monitor + * + * @param logMonitor a log monitor + * @return this for fluent API + * @see TaskExecutorMonitor + * @since 2.0.0 + */ + public TaskExecutorAsserterBuilder setLogMonitor(TaskExecutorMonitor logMonitor) { + this.logMonitor = logMonitor; + return this; + } + + /** + * Set a task result verification when unable to schedule task + * + * @param unableSchedule a verification when unable to schedule task + * @return this for fluent API + * @see TaskResult + * @see TaskExecutorMonitor#onUnableSchedule(TaskResult) + */ + public TaskExecutorAsserterBuilder setUnableSchedule(Consumer unableSchedule) { this.unableSchedule = unableSchedule; return this; } - public TaskExecutorAsserterBuilder schedule(Consumer schedule) { + /** + * Set a task result verification when schedule task + * + * @param schedule a verification when schedule task + * @return this for fluent API + * @see TaskResult + * @see TaskExecutorMonitor#onSchedule(TaskResult) + */ + public TaskExecutorAsserterBuilder setSchedule(Consumer schedule) { this.schedule = schedule; return this; } - public TaskExecutorAsserterBuilder misfire(Consumer misfire) { + /** + * Set a task result verification when misfire task + * + * @param misfire a verification when misfire task + * @return this for fluent API + * @see TaskResult + * @see TaskExecutorMonitor#onMisfire(TaskResult) + */ + public TaskExecutorAsserterBuilder setMisfire(Consumer misfire) { this.misfire = misfire; return this; } - public TaskExecutorAsserterBuilder each(Consumer each) { + /** + * Set a task result verification when each round is finished + * + * @param each a verification when each round is finished of schedule + * @return this for fluent API + * @see TaskResult + * @see TaskExecutorMonitor#onEach(TaskResult) + */ + public TaskExecutorAsserterBuilder setEach(Consumer each) { this.each = each; return this; } - public TaskExecutorAsserterBuilder completed(Consumer completed) { + /** + * Set a task result verification when execution is completed + * + * @param completed a verification when execution is completed + * @return this for fluent API + * @see TaskResult + * @see TaskExecutorMonitor#onCompleted(TaskResult) + */ + public TaskExecutorAsserterBuilder setCompleted(Consumer completed) { this.completed = completed; return this; } + /** + * Build an asserter + * + * @return TaskExecutorAsserter + */ public TaskExecutorAsserter build() { - return new TaskExecutorAsserter(this.testContext, this.unableSchedule, this.schedule, this.misfire, - this.each, this.completed); + return new TaskExecutorAsserter(testContext, logMonitor, unableSchedule, schedule, misfire, each, + completed); } } From 95cf2df8958c2c731ff025bf17c898cb85755dd4 Mon Sep 17 00:00:00 2001 From: zero88 Date: Wed, 26 Jul 2023 13:10:30 +0700 Subject: [PATCH 3/5] refactor(#48): oranize the project package + add javadoc --- .../zero88/schedulerx/CronTaskExecutor.java | 10 -- .../schedulerx/IntervalTaskExecutor.java | 10 -- .../github/zero88/schedulerx/TaskResult.java | 4 - .../TriggerTaskExecutorBuilder.java | 2 + .../schedulerx/impl/AbstractTaskExecutor.java | 122 +++++++++--------- .../impl/AbstractTaskExecutorBuilder.java | 7 +- .../impl/CronTaskExecutorBuilder.java | 15 --- .../impl/IntervalTaskExecutorBuilder.java | 15 --- .../impl/TaskExecutionContextImpl.java | 6 +- .../impl/TaskExecutionContextInternal.java | 2 +- .../impl/TaskExecutorStateImpl.java | 2 +- .../impl/TaskExecutorStateInternal.java | 2 +- .../schedulerx/impl/TaskResultBuilder.java | 84 ------------ .../schedulerx/impl/TaskResultImpl.java | 93 ++++++++++++- .../zero88/schedulerx/impl/package-info.java | 5 + .../zero88/schedulerx/package-info.java | 5 + .../schedulerx/trigger/CronExpression.java | 34 ++--- .../schedulerx/trigger/CronTrigger.java | 3 + .../trigger/CronTriggerExecutor.java | 15 +++ .../trigger/CronTriggerExecutorBuilder.java | 19 +++ .../CronTriggerExecutorImpl.java} | 11 +- .../schedulerx/trigger/IntervalTrigger.java | 3 + .../trigger/IntervalTriggerExecutor.java | 15 +++ .../IntervalTriggerExecutorBuilder.java | 19 +++ .../IntervalTriggerExecutorImpl.java} | 22 ++-- .../schedulerx/trigger/package-info.java | 7 + .../schedulerx/custom/HttpClientTask.java | 4 +- .../schedulerx/custom/HttpClientTaskTest.java | 18 +-- .../CronTriggerExecutorTest.java} | 35 ++--- .../IntervalTriggerExecutorTest.java} | 78 +++++------ .../schedulerx/TaskExecutorAsserter.java | 2 +- 31 files changed, 362 insertions(+), 307 deletions(-) delete mode 100644 core/src/main/java/io/github/zero88/schedulerx/CronTaskExecutor.java delete mode 100644 core/src/main/java/io/github/zero88/schedulerx/IntervalTaskExecutor.java delete mode 100644 core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorBuilder.java delete mode 100644 core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorBuilder.java delete mode 100644 core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultBuilder.java create mode 100644 core/src/main/java/io/github/zero88/schedulerx/impl/package-info.java create mode 100644 core/src/main/java/io/github/zero88/schedulerx/package-info.java create mode 100644 core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutor.java create mode 100644 core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java rename core/src/main/java/io/github/zero88/schedulerx/{impl/CronTaskExecutorImpl.java => trigger/CronTriggerExecutorImpl.java} (69%) create mode 100644 core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java create mode 100644 core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java rename core/src/main/java/io/github/zero88/schedulerx/{impl/IntervalTaskExecutorImpl.java => trigger/IntervalTriggerExecutorImpl.java} (59%) create mode 100644 core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java rename core/src/test/java/io/github/zero88/schedulerx/{CronTaskExecutorTest.java => trigger/CronTriggerExecutorTest.java} (66%) rename core/src/test/java/io/github/zero88/schedulerx/{IntervalTaskExecutorTest.java => trigger/IntervalTriggerExecutorTest.java} (66%) diff --git a/core/src/main/java/io/github/zero88/schedulerx/CronTaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/CronTaskExecutor.java deleted file mode 100644 index 2c19eb6..0000000 --- a/core/src/main/java/io/github/zero88/schedulerx/CronTaskExecutor.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.zero88.schedulerx; - -import io.github.zero88.schedulerx.impl.CronTaskExecutorBuilder; -import io.github.zero88.schedulerx.trigger.CronTrigger; - -public interface CronTaskExecutor extends TriggerTaskExecutor { - - static CronTaskExecutorBuilder builder() { return new CronTaskExecutorBuilder(); } - -} diff --git a/core/src/main/java/io/github/zero88/schedulerx/IntervalTaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/IntervalTaskExecutor.java deleted file mode 100644 index 98b83ff..0000000 --- a/core/src/main/java/io/github/zero88/schedulerx/IntervalTaskExecutor.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.github.zero88.schedulerx; - -import io.github.zero88.schedulerx.impl.IntervalTaskExecutorBuilder; -import io.github.zero88.schedulerx.trigger.IntervalTrigger; - -public interface IntervalTaskExecutor extends TriggerTaskExecutor { - - static IntervalTaskExecutorBuilder builder() { return new IntervalTaskExecutorBuilder(); } - -} diff --git a/core/src/main/java/io/github/zero88/schedulerx/TaskResult.java b/core/src/main/java/io/github/zero88/schedulerx/TaskResult.java index 3b1d2b4..3e53e00 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TaskResult.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TaskResult.java @@ -5,8 +5,6 @@ import org.jetbrains.annotations.Nullable; -import io.github.zero88.schedulerx.impl.TaskResultBuilder; - /** * Represents for task result will be pass on each event of {@link TaskExecutorMonitor} * @@ -15,8 +13,6 @@ */ public interface TaskResult { - static TaskResultBuilder builder() { return new TaskResultBuilder(); } - /** * Only {@code not null} in {@link TaskExecutorMonitor#onUnableSchedule(TaskResult)} * diff --git a/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java index f89b4fc..9c88ef2 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java @@ -6,6 +6,8 @@ import io.vertx.core.Vertx; /** + * Represents for the high level of a builder that construct {@code TriggerTaskExecutor} + * * @param Type of Trigger * @param Type of Trigger Task Executor * @param Type of Executor Builder diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java index 6b732fc..4e1aa28 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java @@ -21,6 +21,11 @@ import io.vertx.core.impl.logging.Logger; import io.vertx.core.impl.logging.LoggerFactory; +/** + * The base task executor + * + * @param Type of trigger + */ public abstract class AbstractTaskExecutor implements TriggerTaskExecutor { @SuppressWarnings("java:S3416") @@ -49,39 +54,39 @@ protected AbstractTaskExecutor(@NotNull Vertx vertx, @NotNull TaskExecutorMonito } @Override - public @NotNull TaskExecutorState state() { return state; } + public final @NotNull TaskExecutorState state() { return state; } @Override - public @NotNull Vertx vertx() { return this.vertx; } + public final @NotNull Vertx vertx() { return this.vertx; } @Override - public @NotNull TaskExecutorMonitor monitor() { return this.monitor; } + public final @NotNull TaskExecutorMonitor monitor() { return this.monitor; } @Override - public @NotNull JobData jobData() { return this.jobData; } + public final @NotNull JobData jobData() { return this.jobData; } @Override - public @NotNull Task task() { return this.task; } + public final @NotNull Task task() { return this.task; } @Override @SuppressWarnings("unchecked") public @NotNull T trigger() { return (T) this.trigger.validate(); } @Override - public void start(WorkerExecutor workerExecutor) { + public final void start(WorkerExecutor workerExecutor) { this.addTimer(Promise.promise(), workerExecutor) .onSuccess(this::onReceiveTimer) - .onFailure(t -> monitor().onUnableSchedule(TaskResult.builder() - .setTick(state().tick()) - .setRound(state().round()) - .setAvailableAt(state().availableAt()) - .setUnscheduledAt(Instant.now()) - .setError(t) - .build())); + .onFailure(t -> monitor().onUnableSchedule(TaskResultImpl.builder() + .setTick(state().tick()) + .setRound(state().round()) + .setAvailableAt(state().availableAt()) + .setUnscheduledAt(Instant.now()) + .setError(t) + .build())); } @Override - public void executeTask(@NotNull TaskExecutionContext executionContext) { + public final void executeTask(@NotNull TaskExecutionContext executionContext) { try { debug(state().tick(), state.round(), executionContext.executedAt(), "Executing task"); task.execute(jobData(), executionContext); @@ -97,7 +102,7 @@ public void executeTask(@NotNull TaskExecutionContext executionContext) { } @Override - public void cancel() { + public final void cancel() { if (!state().completed()) { debug(state().tick(), state().round(), Instant.now(), "Canceling task"); vertx().cancelTimer(state().timerId()); @@ -109,53 +114,54 @@ public void cancel() { protected abstract boolean shouldCancel(long round); - protected void debug(long tick, long round, @NotNull Instant at, @NotNull String event) { + protected final void debug(long tick, long round, @NotNull Instant at, @NotNull String event) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("TaskExecutor[" + tick + "][" + round + "][" + at + "]::" + event); } } - protected void onReceiveTimer(long timerId) { + protected final void onReceiveTimer(long timerId) { TaskResult result; if (state().pending()) { - result = TaskResult.builder().setAvailableAt(state.timerId(timerId).markAvailable().availableAt()).build(); + result = TaskResultImpl.builder() + .setAvailableAt(state.timerId(timerId).markAvailable().availableAt()) + .build(); } else { - result = TaskResult.builder() - .setTick(state.timerId(timerId).tick()) - .setRound(state().round()) - .setAvailableAt(state().availableAt()) - .setRescheduledAt(Instant.now()) - .build(); + result = TaskResultImpl.builder() + .setTick(state.timerId(timerId).tick()) + .setRound(state().round()) + .setAvailableAt(state().availableAt()) + .setRescheduledAt(Instant.now()) + .build(); } monitor().onSchedule(result); } - protected void run(WorkerExecutor workerExecutor) { + protected final void run(WorkerExecutor workerExecutor) { final Instant triggerAt = Instant.now(); if (shouldRun(triggerAt)) { - final TaskExecutionContextImpl context = new TaskExecutionContextImpl(vertx(), state.increaseRound(), - triggerAt); - debug(state().tick(), context.round(), triggerAt, "Trigger executing task"); + TaskExecutionContextInternal ctx = new TaskExecutionContextImpl(vertx(), state.increaseRound(), triggerAt); + debug(state().tick(), ctx.round(), triggerAt, "Trigger executing task"); if (workerExecutor != null) { - workerExecutor.executeBlocking(promise -> executeTask(setupContext(promise, context)), this::onResult); + workerExecutor.executeBlocking(promise -> executeTask(setupContext(promise, ctx)), this::onResult); } else { - vertx().executeBlocking(promise -> executeTask(setupContext(promise, context)), this::onResult); + vertx().executeBlocking(promise -> executeTask(setupContext(promise, ctx)), this::onResult); } } } - protected boolean shouldRun(@NotNull Instant triggerAt) { + protected final boolean shouldRun(@NotNull Instant triggerAt) { final long tick = state.increaseTick(); if (state().completed()) { debug(tick, state().round(), triggerAt, "Execution is already completed"); } if (state().executing()) { debug(tick, state().round(), triggerAt, "Skip execution due to task is still running"); - monitor().onMisfire(TaskResult.builder() - .setAvailableAt(state().availableAt()) - .setTick(state().tick()) - .setTriggeredAt(triggerAt) - .build()); + monitor().onMisfire(TaskResultImpl.builder() + .setAvailableAt(state().availableAt()) + .setTick(state().tick()) + .setTriggeredAt(triggerAt) + .build()); } return state().idle(); } @@ -166,7 +172,7 @@ private TaskExecutionContextInternal setupContext(@NotNull Promise promi return executionContext.setup(promise, Instant.now()); } - protected void onResult(@NotNull AsyncResult asyncResult) { + protected final void onResult(@NotNull AsyncResult asyncResult) { state.markIdle(); final Instant finishedAt = Instant.now(); if (asyncResult.failed()) { @@ -176,36 +182,36 @@ protected void onResult(@NotNull AsyncResult asyncResult) { if (asyncResult.succeeded()) { final TaskExecutionContextInternal result = (TaskExecutionContextInternal) asyncResult.result(); debug(state().tick(), result.round(), finishedAt, "Handling task result"); - monitor().onEach(TaskResult.builder() - .setAvailableAt(state().availableAt()) - .setTick(state().tick()) - .setRound(result.round()) - .setTriggeredAt(result.triggeredAt()) - .setExecutedAt(result.executedAt()) - .setFinishedAt(finishedAt) - .setData(state.addData(result.round(), result.data())) - .setError(state.addError(result.round(), result.error())) - .setCompleted(state().completed()) - .build()); + monitor().onEach(TaskResultImpl.builder() + .setAvailableAt(state().availableAt()) + .setTick(state().tick()) + .setRound(result.round()) + .setTriggeredAt(result.triggeredAt()) + .setExecutedAt(result.executedAt()) + .setFinishedAt(finishedAt) + .setData(state.addData(result.round(), result.data())) + .setError(state.addError(result.round(), result.error())) + .setCompleted(state().completed()) + .build()); } if (shouldCancel(state().round())) { cancel(); } } - protected void onCompleted() { + protected final void onCompleted() { state.markCompleted(); final Instant completedAt = Instant.now(); debug(state().tick(), state().round(), completedAt, "Execution is completed"); - monitor().onCompleted(TaskResult.builder() - .setAvailableAt(state().availableAt()) - .setTick(state().tick()) - .setRound(state().round()) - .setCompleted(state().completed()) - .setCompletedAt(completedAt) - .setData(state().lastData()) - .setError(state().lastError()) - .build()); + monitor().onCompleted(TaskResultImpl.builder() + .setAvailableAt(state().availableAt()) + .setTick(state().tick()) + .setRound(state().round()) + .setCompleted(state().completed()) + .setCompletedAt(completedAt) + .setData(state().lastData()) + .setError(state().lastError()) + .build()); } } diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutorBuilder.java index 4395bf2..8d01e59 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutorBuilder.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutorBuilder.java @@ -13,9 +13,12 @@ import io.github.zero88.schedulerx.trigger.Trigger; import io.vertx.core.Vertx; +/** + * The base task executor builder + */ @SuppressWarnings("unchecked") -abstract class AbstractTaskExecutorBuilder, - B extends AbstractTaskExecutorBuilder> +public abstract class AbstractTaskExecutorBuilder, + B extends AbstractTaskExecutorBuilder> implements TriggerTaskExecutorBuilder { private Vertx vertx; diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorBuilder.java deleted file mode 100644 index c313f5f..0000000 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.zero88.schedulerx.impl; - -import org.jetbrains.annotations.NotNull; - -import io.github.zero88.schedulerx.CronTaskExecutor; -import io.github.zero88.schedulerx.trigger.CronTrigger; - -public final class CronTaskExecutorBuilder - extends AbstractTaskExecutorBuilder { - - public @NotNull CronTaskExecutor build() { - return new CronTaskExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); - } - -} diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorBuilder.java deleted file mode 100644 index 8a1c423..0000000 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.zero88.schedulerx.impl; - -import org.jetbrains.annotations.NotNull; - -import io.github.zero88.schedulerx.IntervalTaskExecutor; -import io.github.zero88.schedulerx.trigger.IntervalTrigger; - -public class IntervalTaskExecutorBuilder - extends AbstractTaskExecutorBuilder { - - public @NotNull IntervalTaskExecutor build() { - return new IntervalTaskExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); - } - -} diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextImpl.java b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextImpl.java index 07f4776..680450f 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextImpl.java @@ -8,7 +8,7 @@ import io.vertx.core.Promise; import io.vertx.core.Vertx; -public final class TaskExecutionContextImpl implements TaskExecutionContextInternal { +final class TaskExecutionContextImpl implements TaskExecutionContextInternal { private final Vertx vertx; private final long round; @@ -57,13 +57,13 @@ public void forceStopExecution() { @Override public void complete(Object data) { this.data = data; - promise.tryComplete(this); + this.internalComplete(); } @Override public void fail(Throwable throwable) { this.error = throwable; - promise.tryComplete(this); + this.internalComplete(); } @Override diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextInternal.java b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextInternal.java index 2a607a8..0b3c591 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextInternal.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutionContextInternal.java @@ -8,7 +8,7 @@ import io.github.zero88.schedulerx.TaskExecutionContext; import io.vertx.core.Promise; -public interface TaskExecutionContextInternal extends TaskExecutionContext { +interface TaskExecutionContextInternal extends TaskExecutionContext { /** * Setup task execution context diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateImpl.java b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateImpl.java index cf1970d..2efd2bf 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateImpl.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; -public final class TaskExecutorStateImpl implements TaskExecutorStateInternal { +final class TaskExecutorStateImpl implements TaskExecutorStateInternal { private final AtomicReference availableAt = new AtomicReference<>(); private final AtomicLong tick = new AtomicLong(0); diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateInternal.java b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateInternal.java index 9ed3970..613046b 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateInternal.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskExecutorStateInternal.java @@ -5,7 +5,7 @@ import io.github.zero88.schedulerx.TaskExecutorState; -public interface TaskExecutorStateInternal extends TaskExecutorState { +interface TaskExecutorStateInternal extends TaskExecutorState { /** * Add timer id diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultBuilder.java deleted file mode 100644 index 56cf854..0000000 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultBuilder.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.github.zero88.schedulerx.impl; - -import java.time.Instant; - -import io.github.zero88.schedulerx.TaskResult; - -public final class TaskResultBuilder { - - Instant unscheduledAt; - Instant rescheduledAt; - Instant availableAt; - Instant triggeredAt; - Instant executedAt; - Instant finishedAt; - Instant completedAt; - long tick; - long round; - boolean completed; - Throwable error; - Object data; - - public TaskResultBuilder setUnscheduledAt(Instant unscheduledAt) { - this.unscheduledAt = unscheduledAt; - return this; - } - - public TaskResultBuilder setRescheduledAt(Instant rescheduledAt) { - this.rescheduledAt = rescheduledAt; - return this; - } - - public TaskResultBuilder setAvailableAt(Instant availableAt) { - this.availableAt = availableAt; - return this; - } - - public TaskResultBuilder setTriggeredAt(Instant triggeredAt) { - this.triggeredAt = triggeredAt; - return this; - } - - public TaskResultBuilder setExecutedAt(Instant executedAt) { - this.executedAt = executedAt; - return this; - } - - public TaskResultBuilder setFinishedAt(Instant finishedAt) { - this.finishedAt = finishedAt; - return this; - } - - public TaskResultBuilder setCompletedAt(Instant completedAt) { - this.completedAt = completedAt; - return this; - } - - public TaskResultBuilder setTick(long tick) { - this.tick = tick; - return this; - } - - public TaskResultBuilder setRound(long round) { - this.round = round; - return this; - } - - public TaskResultBuilder setCompleted(boolean completed) { - this.completed = completed; - return this; - } - - public TaskResultBuilder setError(Throwable error) { - this.error = error; - return this; - } - - public TaskResultBuilder setData(Object data) { - this.data = data; - return this; - } - - public TaskResult build() { return new TaskResultImpl(this); } - -} diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultImpl.java b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultImpl.java index f1773f0..5034767 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/TaskResultImpl.java @@ -4,7 +4,7 @@ import io.github.zero88.schedulerx.TaskResult; -public final class TaskResultImpl implements TaskResult { +final class TaskResultImpl implements TaskResult { private final Instant unscheduledAt; private final Instant rescheduledAt; @@ -58,4 +58,95 @@ public final class TaskResultImpl implements TaskResult { public Object data() { return this.data; } + /** + * Create builder + * + * @return TaskResultBuilder + */ + static TaskResultBuilder builder() { return new TaskResultBuilder(); } + + /** + * Represents a builder that constructs {@link TaskResult} + * + * @see TaskResult + */ + static final class TaskResultBuilder { + + Instant unscheduledAt; + Instant rescheduledAt; + Instant availableAt; + Instant triggeredAt; + Instant executedAt; + Instant finishedAt; + Instant completedAt; + long tick; + long round; + boolean completed; + Throwable error; + Object data; + + public TaskResultBuilder setUnscheduledAt(Instant unscheduledAt) { + this.unscheduledAt = unscheduledAt; + return this; + } + + public TaskResultBuilder setRescheduledAt(Instant rescheduledAt) { + this.rescheduledAt = rescheduledAt; + return this; + } + + public TaskResultBuilder setAvailableAt(Instant availableAt) { + this.availableAt = availableAt; + return this; + } + + public TaskResultBuilder setTriggeredAt(Instant triggeredAt) { + this.triggeredAt = triggeredAt; + return this; + } + + public TaskResultBuilder setExecutedAt(Instant executedAt) { + this.executedAt = executedAt; + return this; + } + + public TaskResultBuilder setFinishedAt(Instant finishedAt) { + this.finishedAt = finishedAt; + return this; + } + + public TaskResultBuilder setCompletedAt(Instant completedAt) { + this.completedAt = completedAt; + return this; + } + + public TaskResultBuilder setTick(long tick) { + this.tick = tick; + return this; + } + + public TaskResultBuilder setRound(long round) { + this.round = round; + return this; + } + + public TaskResultBuilder setCompleted(boolean completed) { + this.completed = completed; + return this; + } + + public TaskResultBuilder setError(Throwable error) { + this.error = error; + return this; + } + + public TaskResultBuilder setData(Object data) { + this.data = data; + return this; + } + + public TaskResult build() { return new TaskResultImpl(this); } + + } + } diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/package-info.java b/core/src/main/java/io/github/zero88/schedulerx/impl/package-info.java new file mode 100644 index 0000000..2adbb33 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/package-info.java @@ -0,0 +1,5 @@ +/** + * The scheduler.x internal implementation. + */ + +package io.github.zero88.schedulerx.impl; diff --git a/core/src/main/java/io/github/zero88/schedulerx/package-info.java b/core/src/main/java/io/github/zero88/schedulerx/package-info.java new file mode 100644 index 0000000..f276a08 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/package-info.java @@ -0,0 +1,5 @@ +/** + * The scheduler.x core API + */ + +package io.github.zero88.schedulerx; diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronExpression.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronExpression.java index cf8b98f..43532ca 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronExpression.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronExpression.java @@ -1,5 +1,3 @@ -package io.github.zero88.schedulerx.trigger; - /* * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. * @@ -17,6 +15,8 @@ * */ +package io.github.zero88.schedulerx.trigger; + import java.io.Serializable; import java.text.ParseException; import java.util.Calendar; @@ -500,7 +500,7 @@ protected int storeExpressionVals(int pos, String s, int type) throws ParseExcep c = s.charAt(i + 3); if (c == '-') { i += 4; - sub = s.substring(i, i + 3); + sub = s.substring(i, i + 3); eval = getMonthNumber(sub) + 1; if (eval <= 0) { throw new ParseException("Invalid Month value: '" + sub + "'", i); @@ -516,7 +516,7 @@ protected int storeExpressionVals(int pos, String s, int type) throws ParseExcep c = s.charAt(i + 3); if (c == '-') { i += 4; - sub = s.substring(i, i + 3); + sub = s.substring(i, i + 3); eval = getDayOfWeekNumber(sub); if (eval < 0) { throw new ParseException("Invalid Day-of-Week value: '" + sub + "'", i); @@ -631,7 +631,7 @@ protected int storeExpressionVals(int pos, String s, int type) throws ParseExcep if (c >= '0' && c <= '9') { ValueSet vs = getValue(val, s, i); val = vs.value; - i = vs.pos; + i = vs.pos; } i = checkNext(i, s, val, type); return i; @@ -734,7 +734,7 @@ protected int checkNext(int pos, String s, int val, int type) throws ParseExcept if (c >= '0' && c <= '9') { ValueSet vs = getValue(v, s, i); end = vs.value; - i = vs.pos; + i = vs.pos; } if (i < s.length() && ((c = s.charAt(i)) == '/')) { i++; @@ -1074,7 +1074,7 @@ protected ValueSet getValue(int v, String s, int i) { } ValueSet val = new ValueSet(); - val.pos = (i < s.length()) ? i : i + 1; + val.pos = (i < s.length()) ? i : i + 1; val.value = Integer.parseInt(s1.toString()); return val; } @@ -1150,7 +1150,7 @@ public Date getTimeAfter(Date afterTime) { // get minute................................................. st = minutes.tailSet(min); if (st != null && st.size() != 0) { - t = min; + t = min; min = st.first(); } else { min = minutes.first(); @@ -1171,7 +1171,7 @@ public Date getTimeAfter(Date afterTime) { // get hour................................................... st = hours.tailSet(hr); if (st != null && st.size() != 0) { - t = hr; + t = hr; hr = st.first(); } else { hr = hours.first(); @@ -1200,20 +1200,20 @@ public Date getTimeAfter(Date afterTime) { st = daysOfMonth.tailSet(day); if (lastdayOfMonth) { if (!nearestWeekday) { - t = day; + t = day; day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); day -= lastdayOffset; if (t > day) { mon++; if (mon > 12) { - mon = 1; + mon = 1; tmon = 3333; // ensure test of mon != tmon further below fails cl.add(Calendar.YEAR, 1); } day = 1; } } else { - t = day; + t = day; day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); day -= lastdayOffset; @@ -1250,7 +1250,7 @@ public Date getTimeAfter(Date afterTime) { } } } else if (nearestWeekday) { - t = day; + t = day; day = daysOfMonth.first(); java.util.Calendar tcal = java.util.Calendar.getInstance(getTimeZone()); @@ -1285,7 +1285,7 @@ public Date getTimeAfter(Date afterTime) { mon++; } } else if (st != null && st.size() != 0) { - t = day; + t = day; day = st.first(); // make sure we don't over-run a short month, such as february int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); @@ -1453,7 +1453,7 @@ public Date getTimeAfter(Date afterTime) { // get month................................................... st = months.tailSet(mon); if (st != null && st.size() != 0) { - t = mon; + t = mon; mon = st.first(); } else { mon = months.first(); @@ -1475,12 +1475,12 @@ public Date getTimeAfter(Date afterTime) { // 1-based year = cl.get(Calendar.YEAR); - t = -1; + t = -1; // get year................................................... st = years.tailSet(year); if (st != null && st.size() != 0) { - t = year; + t = year; year = st.first(); } else { return null; // ran out of years... diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTrigger.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTrigger.java index 0bd94b1..8d617b7 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTrigger.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTrigger.java @@ -93,6 +93,9 @@ public String toString() { return "CronTrigger(expression=" + expression + ", timeZone=" + timeZone + ')'; } + /** + * Represents a builder that constructs {@link CronTrigger} + */ @JsonPOJOBuilder(withPrefix = "") public static class CronTriggerBuilder { diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutor.java new file mode 100644 index 0000000..66db436 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutor.java @@ -0,0 +1,15 @@ +package io.github.zero88.schedulerx.trigger; + +import io.github.zero88.schedulerx.TriggerTaskExecutor; + +/** + * Represents for the task executor has an execution loop based on the timer of cron expressions. + * + * @see CronTrigger + * @since 2.0.0 + */ +public interface CronTriggerExecutor extends TriggerTaskExecutor { + + static CronTriggerExecutorBuilder builder() { return new CronTriggerExecutorBuilder(); } + +} diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java new file mode 100644 index 0000000..f44f0f6 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java @@ -0,0 +1,19 @@ +package io.github.zero88.schedulerx.trigger; + +import org.jetbrains.annotations.NotNull; + +import io.github.zero88.schedulerx.impl.AbstractTaskExecutorBuilder; + +/** + * Represents a builder that constructs {@link CronTriggerExecutor} + * + * @since 2.0.0 + */ +public final class CronTriggerExecutorBuilder + extends AbstractTaskExecutorBuilder { + + public @NotNull CronTriggerExecutor build() { + return new CronTriggerExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); + } + +} diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorImpl.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java similarity index 69% rename from core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorImpl.java rename to core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java index 19585d7..43c3a84 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/CronTaskExecutorImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java @@ -1,23 +1,22 @@ -package io.github.zero88.schedulerx.impl; +package io.github.zero88.schedulerx.trigger; import java.time.Instant; import org.jetbrains.annotations.NotNull; -import io.github.zero88.schedulerx.CronTaskExecutor; import io.github.zero88.schedulerx.JobData; import io.github.zero88.schedulerx.Task; import io.github.zero88.schedulerx.TaskExecutorMonitor; -import io.github.zero88.schedulerx.trigger.CronTrigger; +import io.github.zero88.schedulerx.impl.AbstractTaskExecutor; import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.WorkerExecutor; -final class CronTaskExecutorImpl extends AbstractTaskExecutor implements CronTaskExecutor { +final class CronTriggerExecutorImpl extends AbstractTaskExecutor implements CronTriggerExecutor { - CronTaskExecutorImpl(@NotNull Vertx vertx, @NotNull TaskExecutorMonitor monitor, @NotNull JobData jobData, - @NotNull Task task, @NotNull CronTrigger trigger) { + CronTriggerExecutorImpl(@NotNull Vertx vertx, @NotNull TaskExecutorMonitor monitor, @NotNull JobData jobData, + @NotNull Task task, @NotNull CronTrigger trigger) { super(vertx, monitor, jobData, task, trigger); } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTrigger.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTrigger.java index 58ec07e..f5d983d 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTrigger.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTrigger.java @@ -137,6 +137,9 @@ static void validate(long number, boolean allowZero, boolean allowIndefinitely, throw new IllegalArgumentException("Invalid " + msg + " value"); } + /** + * Represents a builder that constructs {@link IntervalTrigger} + */ @JsonPOJOBuilder(withPrefix = "") public static class IntervalTriggerBuilder { diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java new file mode 100644 index 0000000..142cabd --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java @@ -0,0 +1,15 @@ +package io.github.zero88.schedulerx.trigger; + +import io.github.zero88.schedulerx.TriggerTaskExecutor; + +/** + * Represents for the task executor has an execution loop based on interval. + * + * @see IntervalTrigger + * @since 2.0.0 + */ +public interface IntervalTriggerExecutor extends TriggerTaskExecutor { + + static IntervalTriggerExecutorBuilder builder() { return new IntervalTriggerExecutorBuilder(); } + +} diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java new file mode 100644 index 0000000..1590a59 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java @@ -0,0 +1,19 @@ +package io.github.zero88.schedulerx.trigger; + +import org.jetbrains.annotations.NotNull; + +import io.github.zero88.schedulerx.impl.AbstractTaskExecutorBuilder; + +/** + * Represents a builder that constructs {@link IntervalTriggerExecutor} + * + * @since 2.0.0 + */ +public final class IntervalTriggerExecutorBuilder + extends AbstractTaskExecutorBuilder { + + public @NotNull IntervalTriggerExecutor build() { + return new IntervalTriggerExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); + } + +} diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorImpl.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java similarity index 59% rename from core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorImpl.java rename to core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java index eedba1d..cba1bfb 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/IntervalTaskExecutorImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java @@ -1,36 +1,35 @@ -package io.github.zero88.schedulerx.impl; +package io.github.zero88.schedulerx.trigger; import java.time.Instant; import java.util.function.LongSupplier; import org.jetbrains.annotations.NotNull; -import io.github.zero88.schedulerx.IntervalTaskExecutor; import io.github.zero88.schedulerx.JobData; import io.github.zero88.schedulerx.Task; import io.github.zero88.schedulerx.TaskExecutorMonitor; -import io.github.zero88.schedulerx.trigger.IntervalTrigger; +import io.github.zero88.schedulerx.impl.AbstractTaskExecutor; import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.WorkerExecutor; -final class IntervalTaskExecutorImpl extends AbstractTaskExecutor implements IntervalTaskExecutor { +final class IntervalTriggerExecutorImpl extends AbstractTaskExecutor implements + IntervalTriggerExecutor { - IntervalTaskExecutorImpl(@NotNull Vertx vertx, @NotNull TaskExecutorMonitor monitor, @NotNull JobData jobData, - @NotNull Task task, @NotNull IntervalTrigger trigger) { + IntervalTriggerExecutorImpl(@NotNull Vertx vertx, @NotNull TaskExecutorMonitor monitor, @NotNull JobData jobData, + @NotNull Task task, @NotNull IntervalTrigger trigger) { super(vertx, monitor, jobData, task, trigger); } protected @NotNull Future addTimer(@NotNull Promise promise, WorkerExecutor workerExecutor) { try { - final IntervalTrigger trigger = trigger(); - LongSupplier supplier = () -> vertx().setPeriodic(trigger.intervalInMilliseconds(), + LongSupplier supplier = () -> vertx().setPeriodic(trigger().intervalInMilliseconds(), timerId -> run(workerExecutor)); - if (trigger.noDelay()) { + if (trigger().noDelay()) { promise.complete(supplier.getAsLong()); } else { - final long delay = trigger.delayInMilliseconds(); + final long delay = trigger().delayInMilliseconds(); debug(-1, -1, Instant.now(), "delay [" + delay + "ms] then register task in schedule"); vertx().setTimer(delay, ignore -> promise.complete(supplier.getAsLong())); } @@ -42,8 +41,7 @@ final class IntervalTaskExecutorImpl extends AbstractTaskExecutor= trigger.getRepeat(); + return trigger().noRepeatIndefinitely() && round >= trigger().getRepeat(); } } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java new file mode 100644 index 0000000..8f56069 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java @@ -0,0 +1,7 @@ +/** + * Provides the classes and interfaces to define the trigger and its executor. + * + * @since 2.0.0 + */ + +package io.github.zero88.schedulerx.trigger; diff --git a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java index 60823d1..0040f12 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java +++ b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java @@ -1,5 +1,7 @@ package io.github.zero88.schedulerx.custom; +import org.jetbrains.annotations.NotNull; + import io.github.zero88.schedulerx.JobData; import io.github.zero88.schedulerx.Task; import io.github.zero88.schedulerx.TaskExecutionContext; @@ -9,8 +11,6 @@ import io.vertx.core.http.HttpMethod; import io.vertx.core.json.JsonObject; -import org.jetbrains.annotations.NotNull; - public class HttpClientTask implements Task { @Override diff --git a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java index d2dcf16..e911192 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java +++ b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTaskTest.java @@ -6,9 +6,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import io.github.zero88.schedulerx.IntervalTaskExecutor; import io.github.zero88.schedulerx.TaskExecutorAsserter; import io.github.zero88.schedulerx.TaskResult; +import io.github.zero88.schedulerx.trigger.IntervalTriggerExecutor; import io.github.zero88.schedulerx.trigger.IntervalTrigger; import io.vertx.core.Vertx; import io.vertx.core.json.JsonObject; @@ -35,14 +35,14 @@ void test_http_task(Vertx vertx, VertxTestContext testContext) { .setTestContext(testContext) .setEach(verification) .build(); - IntervalTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(IntervalTrigger.builder().interval(3).repeat(2).build()) - .setTask(new HttpClientTask()) - .setMonitor(monitor) - .setJobData(() -> new JsonObject().put("host", host).put("path", path)) - .build() - .start(); + IntervalTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(IntervalTrigger.builder().interval(3).repeat(2).build()) + .setTask(new HttpClientTask()) + .setMonitor(monitor) + .setJobData(() -> new JsonObject().put("host", host).put("path", path)) + .build() + .start(); } } diff --git a/core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java b/core/src/test/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorTest.java similarity index 66% rename from core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java rename to core/src/test/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorTest.java index 7c5d3af..4df7e03 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/CronTaskExecutorTest.java +++ b/core/src/test/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorTest.java @@ -1,4 +1,4 @@ -package io.github.zero88.schedulerx; +package io.github.zero88.schedulerx.trigger; import java.util.function.Consumer; @@ -6,25 +6,26 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import io.github.zero88.schedulerx.trigger.CronTrigger; +import io.github.zero88.schedulerx.TaskExecutorAsserter; +import io.github.zero88.schedulerx.TaskResult; import io.vertx.core.Vertx; import io.vertx.junit5.Checkpoint; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; @ExtendWith(VertxExtension.class) -class CronTaskExecutorTest { +class CronTriggerExecutorTest { @Test void test_unable_schedule_due_to_initial(Vertx vertx, VertxTestContext testContext) { final Checkpoint checkpoint = testContext.checkpoint(2); - CronTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(CronTrigger.builder().expression("0/").build()) - .setTask((jobData, ctx) -> { }) - .setMonitor(TaskExecutorAsserter.unableScheduleAsserter(testContext, checkpoint)) - .build() - .start(); + CronTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(CronTrigger.builder().expression("0/").build()) + .setTask((jobData, ctx) -> { }) + .setMonitor(TaskExecutorAsserter.unableScheduleAsserter(testContext, checkpoint)) + .build() + .start(); } @Test @@ -45,22 +46,22 @@ void test_run_task_by_cron(Vertx vertx, VertxTestContext testContext) { Assertions.assertTrue(result.isCompleted()); Assertions.assertFalse(result.isError()); }; - CronTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(CronTrigger.builder().expression("0/5 * * ? * * *").build()) - .setTask((jobData, ctx) -> { + CronTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(CronTrigger.builder().expression("0/5 * * ? * * *").build()) + .setTask((jobData, ctx) -> { checkpoint.flag(); if (ctx.round() == 2) { ctx.forceStopExecution(); } }) - .setMonitor(TaskExecutorAsserter.builder() + .setMonitor(TaskExecutorAsserter.builder() .setTestContext(testContext) .setSchedule(schedule) .setCompleted(completed) .build()) - .build() - .start(); + .build() + .start(); } } diff --git a/core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java b/core/src/test/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorTest.java similarity index 66% rename from core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java rename to core/src/test/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorTest.java index 902a29e..cd40f69 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/IntervalTaskExecutorTest.java +++ b/core/src/test/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorTest.java @@ -1,4 +1,4 @@ -package io.github.zero88.schedulerx; +package io.github.zero88.schedulerx.trigger; import java.util.function.Consumer; @@ -6,7 +6,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import io.github.zero88.schedulerx.trigger.IntervalTrigger; +import io.github.zero88.schedulerx.Task; +import io.github.zero88.schedulerx.TaskExecutorAsserter; +import io.github.zero88.schedulerx.TaskResult; import io.vertx.core.Vertx; import io.vertx.core.WorkerExecutor; import io.vertx.junit5.Checkpoint; @@ -14,7 +16,7 @@ import io.vertx.junit5.VertxTestContext; @ExtendWith(VertxExtension.class) -class IntervalTaskExecutorTest { +class IntervalTriggerExecutorTest { static void sleep(int millis, VertxTestContext testContext) { try { @@ -27,25 +29,25 @@ static void sleep(int millis, VertxTestContext testContext) { @Test void test_run_task_unable_schedule_due_to_interval(Vertx vertx, VertxTestContext testContext) { final Checkpoint checkpoint = testContext.checkpoint(2); - IntervalTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(IntervalTrigger.builder().interval(-1).build()) - .setTask((jobData, ctx) -> { }) - .setMonitor(TaskExecutorAsserter.unableScheduleAsserter(testContext, checkpoint)) - .build() - .start(); + IntervalTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(IntervalTrigger.builder().interval(-1).build()) + .setTask((jobData, ctx) -> { }) + .setMonitor(TaskExecutorAsserter.unableScheduleAsserter(testContext, checkpoint)) + .build() + .start(); } @Test void test_run_task_unable_schedule_due_to_initial(Vertx vertx, VertxTestContext testContext) { final Checkpoint checkpoint = testContext.checkpoint(2); - IntervalTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(IntervalTrigger.builder().initialDelay(-1).build()) - .setTask((jobData, ctx) -> { }) - .setMonitor(TaskExecutorAsserter.unableScheduleAsserter(testContext, checkpoint)) - .build() - .start(); + IntervalTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(IntervalTrigger.builder().initialDelay(-1).build()) + .setTask((jobData, ctx) -> { }) + .setMonitor(TaskExecutorAsserter.unableScheduleAsserter(testContext, checkpoint)) + .build() + .start(); } @Test @@ -65,17 +67,17 @@ void test_run_task_after_delay(Vertx vertx, VertxTestContext ctx) { Assertions.assertFalse(result.isError()); ctx.completeNow(); }; - IntervalTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(IntervalTrigger.builder().initialDelay(2).interval(2).repeat(2).build()) - .setTask((jobData, context) -> { }) - .setMonitor(TaskExecutorAsserter.builder() + IntervalTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(IntervalTrigger.builder().initialDelay(2).interval(2).repeat(2).build()) + .setTask((jobData, context) -> { }) + .setMonitor(TaskExecutorAsserter.builder() .setTestContext(ctx) .setSchedule(s) .setCompleted(c) .build()) - .build() - .start(worker); + .build() + .start(worker); } @Test @@ -88,17 +90,17 @@ void test_run_blocking_task_in_the_end(Vertx vertx, VertxTestContext testContext Assertions.assertTrue(result.isCompleted()); Assertions.assertFalse(result.isError()); }; - IntervalTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(IntervalTrigger.builder().interval(2).repeat(3).build()) - .setTask((jobData, ctx) -> { + IntervalTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(IntervalTrigger.builder().interval(2).repeat(3).build()) + .setTask((jobData, ctx) -> { sleep(3000, testContext); checkpoint.flag(); }) - .setMonitor( + .setMonitor( TaskExecutorAsserter.builder().setTestContext(testContext).setCompleted(c).build()) - .build() - .start(worker); + .build() + .start(worker); } @Test @@ -135,17 +137,17 @@ void test_cancel_task_in_condition(Vertx vertx, VertxTestContext context) { Assertions.assertTrue(result.isCompleted()); Assertions.assertFalse(result.isError()); }; - IntervalTaskExecutor.builder() - .setVertx(vertx) - .setTrigger(IntervalTrigger.builder().interval(1).repeat(10).build()) - .setTask(task) - .setMonitor(TaskExecutorAsserter.builder() + IntervalTriggerExecutor.builder() + .setVertx(vertx) + .setTrigger(IntervalTrigger.builder().interval(1).repeat(10).build()) + .setTask(task) + .setMonitor(TaskExecutorAsserter.builder() .setTestContext(context) .setEach(e) .setCompleted(c) .build()) - .build() - .start(); + .build() + .start(); } } diff --git a/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java b/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java index 39c0a84..7f6b8e1 100644 --- a/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java +++ b/core/src/testFixtures/java/io/github/zero88/schedulerx/TaskExecutorAsserter.java @@ -87,7 +87,7 @@ private void verify(@NotNull TaskResult result, Consumer verificatio } @SuppressWarnings("java:S5960") - static TaskExecutorMonitor unableScheduleAsserter(VertxTestContext testContext, Checkpoint checkpoint) { + public static TaskExecutorMonitor unableScheduleAsserter(VertxTestContext testContext, Checkpoint checkpoint) { return TaskExecutorAsserter.builder().setTestContext(testContext).setUnableSchedule(result -> { checkpoint.flag(); Assertions.assertNotNull(result.unscheduledAt()); From f62bd89785a43793d8bccb931a355fe1e19fbc67 Mon Sep 17 00:00:00 2001 From: zero88 Date: Wed, 26 Jul 2023 13:12:20 +0700 Subject: [PATCH 4/5] refactor(#48): TriggerTaskExecutor.trigger() should be cached --- .../schedulerx/impl/AbstractTaskExecutor.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java index 4e1aa28..b8e897e 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/impl/AbstractTaskExecutor.java @@ -1,6 +1,8 @@ package io.github.zero88.schedulerx.impl; import java.time.Instant; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.jetbrains.annotations.NotNull; @@ -42,6 +44,9 @@ public abstract class AbstractTaskExecutor implements Trigger private final Task task; @NotNull private final T trigger; + private final Lock lock = new ReentrantLock(); + private boolean didTriggerValidation = false; + private IllegalArgumentException invalidTrigger; protected AbstractTaskExecutor(@NotNull Vertx vertx, @NotNull TaskExecutorMonitor monitor, @NotNull JobData jobData, @NotNull Task task, @NotNull T trigger) { @@ -69,8 +74,26 @@ protected AbstractTaskExecutor(@NotNull Vertx vertx, @NotNull TaskExecutorMonito public final @NotNull Task task() { return this.task; } @Override - @SuppressWarnings("unchecked") - public @NotNull T trigger() { return (T) this.trigger.validate(); } + public final @NotNull T trigger() { + lock.lock(); + try { + if (didTriggerValidation) { + if (invalidTrigger == null) { return trigger; } + throw invalidTrigger; + } + try { + //noinspection unchecked + return (T) this.trigger.validate(); + } catch (IllegalArgumentException ex) { + this.invalidTrigger = ex; + throw ex; + } finally { + didTriggerValidation = true; + } + } finally { + lock.unlock(); + } + } @Override public final void start(WorkerExecutor workerExecutor) { From df43280790b324c39c2690df495c35d96652bf4e Mon Sep 17 00:00:00 2001 From: zero88 Date: Thu, 27 Jul 2023 10:35:49 +0700 Subject: [PATCH 5/5] feat(#48): Add codegen for rx3/mutiny --- buildSrc/src/main/kotlin/Dependencies.kt | 10 ++++ core/build.gradle.kts | 12 +++++ .../zero88/schedulerx/TaskExecutor.java | 24 +++------ .../schedulerx/TaskExecutorMonitor.java | 4 +- .../schedulerx/TaskExecutorProperties.java | 53 +++++++++++++++++++ .../schedulerx/TriggerTaskExecutor.java | 17 +----- .../TriggerTaskExecutorBuilder.java | 15 ++---- .../impl/AbstractTaskExecutorBuilder.java | 52 +++++++++--------- .../zero88/schedulerx/package-info.java | 4 ++ .../trigger/CronTriggerExecutor.java | 11 +++- .../trigger/CronTriggerExecutorBuilder.java | 40 +++++++++++--- .../trigger/CronTriggerExecutorImpl.java | 11 ++++ .../trigger/IntervalTriggerExecutor.java | 11 +++- .../IntervalTriggerExecutorBuilder.java | 41 +++++++++++--- .../trigger/IntervalTriggerExecutorImpl.java | 15 +++++- .../schedulerx/trigger/package-info.java | 3 ++ .../schedulerx/custom/HttpClientTask.java | 36 +++++-------- 17 files changed, 249 insertions(+), 110 deletions(-) create mode 100644 core/src/main/java/io/github/zero88/schedulerx/TaskExecutorProperties.java diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 7e6be2d..aefc24e 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -70,4 +70,14 @@ object VertxLibs { @JvmField val core = "io.vertx:vertx-core:${Version.defaultVersion}" @JvmField val junit5 = "io.vertx:vertx-junit5:${Version.defaultVersion}" + @JvmField val rx3 = "io.vertx:vertx-rx-java3:${Version.defaultVersion}" +} + +object MutinyLibs { + object Version { + + const val mutiny = "2.27.0" + } + + const val core = "io.smallrye.reactive:smallrye-mutiny-vertx-core:${Version.mutiny}" } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index ee2bfc6..5ab5a57 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,8 @@ +import cloud.playio.gradle.generator.codegen.SourceSetName + plugins { `java-test-fixtures` + id(PlayioPlugin.codegen) } @@ -8,11 +11,20 @@ oss { title.set("Scheduler.x") } +codegen { + vertx { + version.set(VertxLibs.Version.defaultVersion) + sources.addAll(arrayOf(SourceSetName.MAIN)) + } +} + dependencies { api(VertxLibs.core) compileOnly(JacksonLibs.annotations) compileOnly(JacksonLibs.databind) compileOnly(UtilLibs.jetbrainsAnnotations) + codeGenerator(VertxLibs.rx3) + codeGenerator(MutinyLibs.core) testImplementation(TestLibs.junit5Params) testImplementation(JacksonLibs.databind) diff --git a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutor.java index b8a9300..25bd3e2 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutor.java @@ -2,39 +2,26 @@ import org.jetbrains.annotations.NotNull; -import io.vertx.core.Vertx; +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.codegen.annotations.VertxGen; import io.vertx.core.WorkerExecutor; /** * Represents for an executor run {@code task} in conditional loop * - * @see TriggerTaskExecutor * @since 1.0.0 */ -public interface TaskExecutor { - - /** - * Vertx - * - * @return vertx - */ - @NotNull Vertx vertx(); +@VertxGen(concrete = false) +public interface TaskExecutor extends TaskExecutorProperties { /** * Task executor state * * @return task executor state */ + @GenIgnore(GenIgnore.PERMITTED_TYPE) @NotNull TaskExecutorState state(); - /** - * Defines a task executor monitor - * - * @return task executor monitor - * @see TaskExecutorMonitor - */ - @NotNull TaskExecutorMonitor monitor(); - /** * Start and run in {@code Vertx worker thread pool} */ @@ -53,6 +40,7 @@ public interface TaskExecutor { * * @param executionContext execution context */ + @GenIgnore(GenIgnore.PERMITTED_TYPE) void executeTask(@NotNull TaskExecutionContext executionContext); /** diff --git a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java index 2a30c83..14d3d87 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorMonitor.java @@ -3,7 +3,9 @@ import org.jetbrains.annotations.NotNull; /** - * Represents for a monitor that watches lifecycle event in executor + * Represents for a monitor that watches lifecycle event in executor. + *

+ * It can be used to persist or distribute the task result per each round. * * @see TaskResult * @since 1.0.0 diff --git a/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorProperties.java b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorProperties.java new file mode 100644 index 0000000..1da1b69 --- /dev/null +++ b/core/src/main/java/io/github/zero88/schedulerx/TaskExecutorProperties.java @@ -0,0 +1,53 @@ +package io.github.zero88.schedulerx; + +import org.jetbrains.annotations.ApiStatus.Internal; +import org.jetbrains.annotations.NotNull; + +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.codegen.annotations.VertxGen; +import io.vertx.core.Vertx; + +/** + * Shared immutable fields between TaskExecutor and its builder + * + * @since 2.0.0 + */ +@Internal +@VertxGen(concrete = false) +public interface TaskExecutorProperties { + + /** + * Vertx + * + * @return vertx + */ + @NotNull Vertx vertx(); + + /** + * Defines a task executor monitor + * + * @return task executor monitor + * @see TaskExecutorMonitor + */ + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull TaskExecutorMonitor monitor(); + + /** + * Task to execute per round + * + * @return task + * @see Task + */ + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull Task task(); + + /** + * Defines job data as input task data + * + * @return job data + * @see JobData + */ + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull JobData jobData(); + +} diff --git a/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutor.java index 586cd18..94f563e 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutor.java @@ -9,6 +9,7 @@ * * @param Type of Trigger * @see Trigger + * @see TaskExecutor * @since 1.0.0 */ public interface TriggerTaskExecutor extends TaskExecutor { @@ -20,20 +21,4 @@ public interface TriggerTaskExecutor extends TaskExecutor { */ @NotNull T trigger(); - /** - * Task to execute per round - * - * @return task - * @see Task - */ - @NotNull Task task(); - - /** - * Defines job data as input task data - * - * @return job data - * @see JobData - */ - @NotNull JobData jobData(); - } diff --git a/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java index 9c88ef2..c731803 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java +++ b/core/src/main/java/io/github/zero88/schedulerx/TriggerTaskExecutorBuilder.java @@ -16,7 +16,10 @@ * @since 2.0.0 */ public interface TriggerTaskExecutorBuilder, - SELF extends TriggerTaskExecutorBuilder> { + SELF extends TriggerTaskExecutorBuilder> + extends TaskExecutorProperties { + + @NotNull TRIGGER trigger(); @NotNull SELF setVertx(@NotNull Vertx vertx); @@ -28,16 +31,6 @@ public interface TriggerTaskExecutorBuilder, - B extends AbstractTaskExecutorBuilder> + B extends TriggerTaskExecutorBuilder> implements TriggerTaskExecutorBuilder { private Vertx vertx; @@ -27,44 +27,48 @@ public abstract class AbstractTaskExecutorBuilder { - static CronTriggerExecutorBuilder builder() { return new CronTriggerExecutorBuilder(); } + static CronTriggerExecutorBuilder builder() { return new CronTriggerExecutorImpl.CronTriggerExecutorBuilderImpl(); } + + @Override + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull CronTrigger trigger(); } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java index f44f0f6..cd84b1d 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorBuilder.java @@ -2,18 +2,46 @@ import org.jetbrains.annotations.NotNull; -import io.github.zero88.schedulerx.impl.AbstractTaskExecutorBuilder; +import io.github.zero88.schedulerx.JobData; +import io.github.zero88.schedulerx.Task; +import io.github.zero88.schedulerx.TaskExecutorMonitor; +import io.github.zero88.schedulerx.TriggerTaskExecutorBuilder; +import io.vertx.codegen.annotations.Fluent; +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.codegen.annotations.VertxGen; +import io.vertx.core.Vertx; /** * Represents a builder that constructs {@link CronTriggerExecutor} * * @since 2.0.0 */ -public final class CronTriggerExecutorBuilder - extends AbstractTaskExecutorBuilder { +@VertxGen +public interface CronTriggerExecutorBuilder + extends TriggerTaskExecutorBuilder { - public @NotNull CronTriggerExecutor build() { - return new CronTriggerExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); - } + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull CronTrigger trigger(); + + @Fluent + @NotNull CronTriggerExecutorBuilder setVertx(@NotNull Vertx vertx); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull CronTriggerExecutorBuilder setTask(@NotNull Task task); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull CronTriggerExecutorBuilder setTrigger(@NotNull CronTrigger trigger); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull CronTriggerExecutorBuilder setJobData(@NotNull JobData jobData); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull CronTriggerExecutorBuilder setMonitor(@NotNull TaskExecutorMonitor monitor); + + @NotNull CronTriggerExecutor build(); } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java index 43c3a84..f612cfa 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/CronTriggerExecutorImpl.java @@ -8,6 +8,7 @@ import io.github.zero88.schedulerx.Task; import io.github.zero88.schedulerx.TaskExecutorMonitor; import io.github.zero88.schedulerx.impl.AbstractTaskExecutor; +import io.github.zero88.schedulerx.impl.AbstractTaskExecutorBuilder; import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.Vertx; @@ -39,4 +40,14 @@ protected boolean shouldCancel(long round) { return false; } + static final class CronTriggerExecutorBuilderImpl + extends AbstractTaskExecutorBuilder + implements CronTriggerExecutorBuilder { + + public @NotNull CronTriggerExecutor build() { + return new CronTriggerExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); + } + + } + } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java index 142cabd..9633c3f 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutor.java @@ -1,6 +1,10 @@ package io.github.zero88.schedulerx.trigger; +import org.jetbrains.annotations.NotNull; + import io.github.zero88.schedulerx.TriggerTaskExecutor; +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.codegen.annotations.VertxGen; /** * Represents for the task executor has an execution loop based on interval. @@ -8,8 +12,13 @@ * @see IntervalTrigger * @since 2.0.0 */ +@VertxGen public interface IntervalTriggerExecutor extends TriggerTaskExecutor { - static IntervalTriggerExecutorBuilder builder() { return new IntervalTriggerExecutorBuilder(); } + static IntervalTriggerExecutorBuilder builder() { return new IntervalTriggerExecutorImpl.IntervalTriggerExecutorBuilderImpl(); } + + @Override + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTrigger trigger(); } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java index 1590a59..c642525 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorBuilder.java @@ -2,18 +2,47 @@ import org.jetbrains.annotations.NotNull; -import io.github.zero88.schedulerx.impl.AbstractTaskExecutorBuilder; +import io.github.zero88.schedulerx.JobData; +import io.github.zero88.schedulerx.Task; +import io.github.zero88.schedulerx.TaskExecutorMonitor; +import io.github.zero88.schedulerx.TriggerTaskExecutorBuilder; +import io.vertx.codegen.annotations.Fluent; +import io.vertx.codegen.annotations.GenIgnore; +import io.vertx.codegen.annotations.VertxGen; +import io.vertx.core.Vertx; /** * Represents a builder that constructs {@link IntervalTriggerExecutor} * * @since 2.0.0 */ -public final class IntervalTriggerExecutorBuilder - extends AbstractTaskExecutorBuilder { +@VertxGen +public interface IntervalTriggerExecutorBuilder + extends TriggerTaskExecutorBuilder { - public @NotNull IntervalTriggerExecutor build() { - return new IntervalTriggerExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); - } + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTrigger trigger(); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTriggerExecutorBuilder setVertx(@NotNull Vertx vertx); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTriggerExecutorBuilder setTask(@NotNull Task task); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTriggerExecutorBuilder setTrigger(@NotNull IntervalTrigger trigger); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTriggerExecutorBuilder setJobData(@NotNull JobData jobData); + + @Fluent + @GenIgnore(GenIgnore.PERMITTED_TYPE) + @NotNull IntervalTriggerExecutorBuilder setMonitor(@NotNull TaskExecutorMonitor monitor); + + @NotNull IntervalTriggerExecutor build(); } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java index cba1bfb..19d6d84 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/IntervalTriggerExecutorImpl.java @@ -9,13 +9,14 @@ import io.github.zero88.schedulerx.Task; import io.github.zero88.schedulerx.TaskExecutorMonitor; import io.github.zero88.schedulerx.impl.AbstractTaskExecutor; +import io.github.zero88.schedulerx.impl.AbstractTaskExecutorBuilder; import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.WorkerExecutor; -final class IntervalTriggerExecutorImpl extends AbstractTaskExecutor implements - IntervalTriggerExecutor { +final class IntervalTriggerExecutorImpl extends AbstractTaskExecutor + implements IntervalTriggerExecutor { IntervalTriggerExecutorImpl(@NotNull Vertx vertx, @NotNull TaskExecutorMonitor monitor, @NotNull JobData jobData, @NotNull Task task, @NotNull IntervalTrigger trigger) { @@ -44,4 +45,14 @@ protected boolean shouldCancel(long round) { return trigger().noRepeatIndefinitely() && round >= trigger().getRepeat(); } + static final class IntervalTriggerExecutorBuilderImpl + extends AbstractTaskExecutorBuilder + implements IntervalTriggerExecutorBuilder { + + public @NotNull IntervalTriggerExecutor build() { + return new IntervalTriggerExecutorImpl(vertx(), monitor(), jobData(), task(), trigger()); + } + + } + } diff --git a/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java b/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java index 8f56069..7043b54 100644 --- a/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java +++ b/core/src/main/java/io/github/zero88/schedulerx/trigger/package-info.java @@ -4,4 +4,7 @@ * @since 2.0.0 */ +@ModuleGen(name = "io-zero88-schedulerx", groupPackage = "io.github.zero88.schedulerx") package io.github.zero88.schedulerx.trigger; + +import io.vertx.codegen.annotations.ModuleGen; diff --git a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java index 0040f12..4a5cc98 100644 --- a/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java +++ b/core/src/test/java/io/github/zero88/schedulerx/custom/HttpClientTask.java @@ -5,9 +5,9 @@ import io.github.zero88.schedulerx.JobData; import io.github.zero88.schedulerx.Task; import io.github.zero88.schedulerx.TaskExecutionContext; +import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientRequest; -import io.vertx.core.http.HttpClientResponse; import io.vertx.core.http.HttpMethod; import io.vertx.core.json.JsonObject; @@ -20,30 +20,18 @@ public boolean isAsync() { @Override public void execute(@NotNull JobData jobData, @NotNull TaskExecutionContext executionContext) { - final Vertx vertx = executionContext.vertx(); + doExecute(executionContext.vertx(), jobData).onSuccess(executionContext::complete) + .onFailure(executionContext::fail); + } + + private Future doExecute(Vertx vertx, @NotNull JobData jobData) { JsonObject url = (JsonObject) jobData.get(); - vertx.createHttpClient().request(HttpMethod.GET, url.getString("host"), url.getString("path"), ar1 -> { - if (ar1.succeeded()) { - HttpClientRequest request = ar1.result(); - request.send(ar2 -> { - if (ar2.succeeded()) { - HttpClientResponse response = ar2.result(); - response.body(ar3 -> { - if (ar3.succeeded()) { - executionContext.complete(new JsonObject().put("status", response.statusCode()) - .put("response", ar3.result().toJson())); - } else { - executionContext.fail(ar3.cause()); - } - }); - } else { - executionContext.fail(ar2.cause()); - } - }); - } else { - executionContext.fail(ar1.cause()); - } - }); + return vertx.createHttpClient() + .request(HttpMethod.GET, url.getString("host"), url.getString("path")) + .flatMap(HttpClientRequest::send) + .flatMap(response -> response.body() + .map(ar3 -> new JsonObject().put("status", response.statusCode()) + .put("response", ar3.toJson()))); } }