From cf8ed7997dd83e8fcc704848bad9656cf6c09c2d Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Sun, 14 Jan 2024 22:12:06 +0800 Subject: [PATCH] [Core] [Schedule] Add local schedule --- pom.xml | 1 + schedule/datacap-schedule-local/pom.xml | 36 +++++++++ .../datacap/schedule/local/LocalSchedule.kt | 15 ++++ .../schedule/local/LocalScheduleModule.kt | 13 ++++ .../datacap/schedule/local/QuartzEndpoint.kt | 76 +++++++++++++++++++ .../io.edurt.datacap.schedule.ScheduleModule | 1 + .../datacap/schedule/local/ExampleJob.kt | 10 +++ .../schedule/local/LocalScheduleModuleTest.kt | 27 +++++++ .../schedule/local/QuartzEndpointTest.kt | 31 ++++++++ schedule/datacap-schedule-spi/pom.xml | 9 +++ .../io/edurt/datacap/schedule/Schedule.kt | 2 - .../io/edurt/datacap/schedule/ScheduleJob.kt | 5 ++ .../edurt/datacap/schedule/ScheduleRequest.kt | 10 +-- .../datacap/schedule/ScheduleResponse.kt | 6 +- .../io/edurt/datacap/schedule/TestSchedule.kt | 4 - 15 files changed, 231 insertions(+), 15 deletions(-) create mode 100644 schedule/datacap-schedule-local/pom.xml create mode 100644 schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalSchedule.kt create mode 100644 schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModule.kt create mode 100644 schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/QuartzEndpoint.kt create mode 100644 schedule/datacap-schedule-local/src/main/resources/META-INF/services/io.edurt.datacap.schedule.ScheduleModule create mode 100644 schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/ExampleJob.kt create mode 100644 schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModuleTest.kt create mode 100644 schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/QuartzEndpointTest.kt create mode 100644 schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleJob.kt diff --git a/pom.xml b/pom.xml index 9b5a4538..5aa8af58 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,7 @@ parser/datacap-parser-trino parser/datacap-parser-mysql schedule/datacap-schedule-spi + schedule/datacap-schedule-local datacap diff --git a/schedule/datacap-schedule-local/pom.xml b/schedule/datacap-schedule-local/pom.xml new file mode 100644 index 00000000..eab8461c --- /dev/null +++ b/schedule/datacap-schedule-local/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + io.edurt.datacap + datacap + 2024.01.1-SNAPSHOT + ../../pom.xml + + + datacap-schedule-local + DataCap - Schedule for local + + + + io.edurt.datacap + datacap-schedule-spi + ${project.version} + + + org.jetbrains.kotlin + kotlin-reflect + provided + + + + + + + org.jetbrains.dokka + dokka-maven-plugin + + + + + diff --git a/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalSchedule.kt b/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalSchedule.kt new file mode 100644 index 00000000..83cf1489 --- /dev/null +++ b/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalSchedule.kt @@ -0,0 +1,15 @@ +package io.edurt.datacap.schedule.local + +import io.edurt.datacap.schedule.Schedule +import io.edurt.datacap.schedule.ScheduleRequest +import io.edurt.datacap.schedule.ScheduleResponse + +class LocalSchedule : Schedule { + override fun initialize(request: ScheduleRequest): ScheduleResponse { + return QuartzEndpoint.createJob(request) + } + + override fun stop(request: ScheduleRequest): ScheduleResponse { + return QuartzEndpoint.removeJob(request) + } +} diff --git a/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModule.kt b/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModule.kt new file mode 100644 index 00000000..929d95e6 --- /dev/null +++ b/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModule.kt @@ -0,0 +1,13 @@ +package io.edurt.datacap.schedule.local + +import com.google.inject.multibindings.Multibinder +import io.edurt.datacap.schedule.Schedule +import io.edurt.datacap.schedule.ScheduleModule + +class LocalScheduleModule : ScheduleModule() { + override fun configure() { + Multibinder.newSetBinder(this.binder(), Schedule::class.java) + .addBinding() + .to(LocalSchedule::class.java) + } +} diff --git a/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/QuartzEndpoint.kt b/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/QuartzEndpoint.kt new file mode 100644 index 00000000..cd86959e --- /dev/null +++ b/schedule/datacap-schedule-local/src/main/kotlin/io/edurt/datacap/schedule/local/QuartzEndpoint.kt @@ -0,0 +1,76 @@ +package io.edurt.datacap.schedule.local + +import io.edurt.datacap.schedule.ScheduleRequest +import io.edurt.datacap.schedule.ScheduleResponse +import org.quartz.* +import org.quartz.impl.StdSchedulerFactory +import org.slf4j.LoggerFactory + + +object QuartzEndpoint { + private val log = LoggerFactory.getLogger(this.javaClass) + private val scheduler: Scheduler = StdSchedulerFactory.getDefaultScheduler() + + @JvmStatic + fun createJob(request: ScheduleRequest): ScheduleResponse { + val response = ScheduleResponse() + val name = getJobName(request) + val group = getJobGroup(request) + try { + val jobDetail: JobDetail = request.job?.let { + JobBuilder.newJob(it::class.java) + .withIdentity(name, group) + .build() + } ?: throw IllegalArgumentException("Job is null") + + val trigger: Trigger = TriggerBuilder.newTrigger() + .withIdentity("trigger-${request.name}", "trigger-group-${request.group}") + .startNow() + .withSchedule(CronScheduleBuilder.cronSchedule(request.expression)) + .build() + + log.info("Add new job [ {} ] to group [ {} ]", name, group) + scheduler.scheduleJob(jobDetail, trigger) + + if (! scheduler.isStarted) { + log.info("Scheduler starting") + scheduler.start() + } + response.successful = true + log.info("Add new job [ {} ] to group [ {} ] successful", name, group) + } + catch (ex: Exception) { + log.info("Add new job [ {} ] to group [ {} ] failure ", name, group, ex) + response.successful = false + response.message = ex.message + } + return response + } + + @JvmStatic + fun removeJob(request: ScheduleRequest): ScheduleResponse { + val response = ScheduleResponse() + val name = getJobName(request) + val group = getJobGroup(request) + try { + log.info("Remove job [ {} ] from group [ {} ]", name, group) + scheduler.deleteJob(JobKey(name, group)) + response.successful = true + log.info("Remove job [ {} ] from group [ {} ] successful", name, group) + } + catch (ex: Exception) { + log.info("Remove job [ {} ] from group [ {} ] failure ", name, group, ex) + response.successful = false + response.message = ex.message + } + return response + } + + private fun getJobName(request: ScheduleRequest): String { + return "job-${request.name}" + } + + private fun getJobGroup(request: ScheduleRequest): String { + return "job-group-${request.group}" + } +} diff --git a/schedule/datacap-schedule-local/src/main/resources/META-INF/services/io.edurt.datacap.schedule.ScheduleModule b/schedule/datacap-schedule-local/src/main/resources/META-INF/services/io.edurt.datacap.schedule.ScheduleModule new file mode 100644 index 00000000..83f2c52d --- /dev/null +++ b/schedule/datacap-schedule-local/src/main/resources/META-INF/services/io.edurt.datacap.schedule.ScheduleModule @@ -0,0 +1 @@ +io.edurt.datacap.schedule.local.LocalScheduleModule diff --git a/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/ExampleJob.kt b/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/ExampleJob.kt new file mode 100644 index 00000000..f75c1bba --- /dev/null +++ b/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/ExampleJob.kt @@ -0,0 +1,10 @@ +package io.edurt.datacap.schedule.local + +import io.edurt.datacap.schedule.ScheduleJob +import org.quartz.JobExecutionContext + +class ExampleJob : ScheduleJob() { + override fun execute(p0: JobExecutionContext?) { + TODO("Not yet implemented") + } +} diff --git a/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModuleTest.kt b/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModuleTest.kt new file mode 100644 index 00000000..c9984ee0 --- /dev/null +++ b/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/LocalScheduleModuleTest.kt @@ -0,0 +1,27 @@ +package io.edurt.datacap.schedule.local + +import com.google.inject.Guice +import com.google.inject.Injector +import com.google.inject.Key +import com.google.inject.TypeLiteral +import io.edurt.datacap.schedule.Schedule +import org.junit.Before +import org.junit.Test +import kotlin.test.assertNotNull + +class LocalScheduleModuleTest { + private val name = "Local" + private var injector: Injector? = null + + @Before + fun before() { + injector = Guice.createInjector(LocalScheduleModule()) + } + + @Test + fun test() { + val schedule: Schedule? = injector?.getInstance(Key.get(object : TypeLiteral?>() {})) + ?.first { v -> v?.name().equals(name) } + assertNotNull(schedule) + } +} diff --git a/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/QuartzEndpointTest.kt b/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/QuartzEndpointTest.kt new file mode 100644 index 00000000..b55bfc45 --- /dev/null +++ b/schedule/datacap-schedule-local/src/test/kotlin/io/edurt/datacap/schedule/local/QuartzEndpointTest.kt @@ -0,0 +1,31 @@ +package io.edurt.datacap.schedule.local + +import io.edurt.datacap.schedule.ScheduleRequest +import org.junit.Before +import org.junit.Test +import kotlin.test.assertTrue + +class QuartzEndpointTest { + private val name: String = "TestJob" + private val group: String = "TestGroup" + private val request = ScheduleRequest() + + @Before + fun before() { + request.name = name + request.group = group + request.expression = "*/10 * * * * ?" + request.job = ExampleJob() + } + + @Test + fun testCreateJob() { + assertTrue(QuartzEndpoint.createJob(request).successful) + } + + @Test + fun testRemoveJob() { + QuartzEndpoint.createJob(request) + assertTrue(QuartzEndpoint.removeJob(request).successful) + } +} diff --git a/schedule/datacap-schedule-spi/pom.xml b/schedule/datacap-schedule-spi/pom.xml index 9422bb08..6fc231c3 100644 --- a/schedule/datacap-schedule-spi/pom.xml +++ b/schedule/datacap-schedule-spi/pom.xml @@ -11,6 +11,10 @@ datacap-schedule-spi DataCap - Schedule spi + + 2.3.2 + + com.google.inject @@ -26,6 +30,11 @@ kotlin-reflect provided + + org.quartz-scheduler + quartz + ${quartz.version} + diff --git a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/Schedule.kt b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/Schedule.kt index 17513124..43a6e3bf 100644 --- a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/Schedule.kt +++ b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/Schedule.kt @@ -9,7 +9,5 @@ interface Schedule { fun initialize(request: ScheduleRequest): ScheduleResponse - fun start(request: ScheduleRequest): ScheduleResponse - fun stop(request: ScheduleRequest): ScheduleResponse } diff --git a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleJob.kt b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleJob.kt new file mode 100644 index 00000000..189dd034 --- /dev/null +++ b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleJob.kt @@ -0,0 +1,5 @@ +package io.edurt.datacap.schedule + +import org.quartz.Job + +abstract class ScheduleJob : Job diff --git a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleRequest.kt b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleRequest.kt index e8695b9d..0a8d042d 100644 --- a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleRequest.kt +++ b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleRequest.kt @@ -1,7 +1,7 @@ package io.edurt.datacap.schedule -class ScheduleRequest { - val name: String? = null - val expression: String? = null - val jobId: String? = null -} +data class ScheduleRequest(var name: String? = null, + var group: String = "DataCap-Schedule-Group", + var expression: String? = null, + var jobId: String? = null, + var job: ScheduleJob? = null) diff --git a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleResponse.kt b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleResponse.kt index e92d36f8..d53b4fcf 100644 --- a/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleResponse.kt +++ b/schedule/datacap-schedule-spi/src/main/kotlin/io/edurt/datacap/schedule/ScheduleResponse.kt @@ -1,6 +1,4 @@ package io.edurt.datacap.schedule -class ScheduleResponse { - val successful: Boolean = false - val message: String? = null -} +data class ScheduleResponse(var successful: Boolean = false, + var message: String? = null) diff --git a/schedule/datacap-schedule-spi/src/test/kotlin/io/edurt/datacap/schedule/TestSchedule.kt b/schedule/datacap-schedule-spi/src/test/kotlin/io/edurt/datacap/schedule/TestSchedule.kt index 81b9b97b..88ff9a3e 100644 --- a/schedule/datacap-schedule-spi/src/test/kotlin/io/edurt/datacap/schedule/TestSchedule.kt +++ b/schedule/datacap-schedule-spi/src/test/kotlin/io/edurt/datacap/schedule/TestSchedule.kt @@ -5,10 +5,6 @@ class TestSchedule : Schedule { TODO("Not yet implemented") } - override fun start(request: ScheduleRequest): ScheduleResponse { - TODO("Not yet implemented") - } - override fun stop(request: ScheduleRequest): ScheduleResponse { TODO("Not yet implemented") }