feat(plugin): adapter scheduler -- local

This commit is contained in:
qianmoQ 2024-11-27 17:52:35 +08:00
parent a2a7cb5b10
commit e14fc43ac2
27 changed files with 348 additions and 175 deletions

View File

@ -7,3 +7,4 @@ datacap-convert-csv=convert/datacap-convert-csv/pom.xml
datacap-convert-none=convert/datacap-convert-none/pom.xml
datacap-executor-local=executor/datacap-executor-local/pom.xml
datacap-executor-seatunnel=executor/datacap-executor-seatunnel/pom.xml
datacap-scheduler-local=scheduler/datacap-scheduler-local/pom.xml

View File

@ -139,6 +139,21 @@
"ALL"
],
"url": "https://cdn.north.devlive.org/applications/datacap/plugins/2024.4.0-SNAPSHOT/executor/datacap-executor-seatunnel-bin.tar.gz"
},
{
"key": "datacap-scheduler-local",
"label": "LocalScheduler",
"description": "A local scheduling plugin for DataCap.",
"i18nFormat": true,
"type": "Scheduler",
"version": "2024.4.0-SNAPSHOT",
"author": "datacap-community",
"logo": "https://cdn.north.devlive.org/applications/datacap/resources/logo/scheduler/local.svg",
"released": "2024-11-21 23:11:15",
"supportVersion": [
"ALL"
],
"url": "https://cdn.north.devlive.org/applications/datacap/plugins/2024.4.0-SNAPSHOT/scheduler/datacap-scheduler-local-bin.tar.gz"
}
]
}

View File

@ -11,3 +11,13 @@ WHERE `version` IS NULL;
UPDATE `datacap_dataset`
SET `executor` = 'LocalExecutor'
WHERE `executor` = 'Default';
ALTER TABLE `datacap_dataset`
ALTER COLUMN `executor` SET DEFAULT 'LocalExecutor';
UPDATE `datacap_dataset`
SET `scheduler` = 'LocalScheduler'
WHERE `scheduler` = 'Default';
ALTER TABLE `datacap_dataset`
ALTER COLUMN `scheduler` SET DEFAULT 'LocalScheduler';

View File

@ -1,5 +1,6 @@
package io.edurt.datacap.plugin;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@ -11,6 +12,7 @@ import java.util.Set;
@Getter
@Builder
@SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
public class PluginConfigure
{
private static final Set<String> LOADER_PACKAGES = Set.of(

View File

@ -1,5 +1,6 @@
package io.edurt.datacap.plugin.loader;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -14,6 +15,7 @@ import java.util.Set;
* Plugin-specific ClassLoader
*/
@Slf4j
@SuppressFBWarnings(value = {"EI_EXPOSE_REP2"})
public class PluginClassLoader
extends URLClassLoader
implements AutoCloseable

View File

@ -500,7 +500,6 @@
<!-- <version>${project.version}</version>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->
<!-- Executor -->
<dependency>
<groupId>io.edurt.datacap</groupId>
<artifactId>datacap-executor-spi</artifactId>
@ -511,13 +510,6 @@
<artifactId>datacap-scheduler-spi</artifactId>
<version>${project.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.edurt.datacap</groupId>-->
<!-- <artifactId>datacap-scheduler-local</artifactId>-->
<!-- <version>${project.version}</version>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->
<!-- Convert -->
</dependencies>
<build>

View File

@ -12,7 +12,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@EnableAsync
@EnableScheduling
@Slf4j
public class ScheduleConfiguration
public class SchedulerConfiguration
{
@Bean
public TaskScheduler taskScheduler()

View File

@ -0,0 +1,62 @@
package io.edurt.datacap.server.runner;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.edurt.datacap.plugin.PluginManager;
import io.edurt.datacap.scheduler.SchedulerRequest;
import io.edurt.datacap.scheduler.SchedulerService;
import io.edurt.datacap.service.enums.SyncMode;
import io.edurt.datacap.service.initializer.job.DatasetJob;
import io.edurt.datacap.service.repository.DataSetRepository;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Scheduler;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
public class SchedulerRunner
implements CommandLineRunner
{
private final PluginManager pluginManager;
private final DataSetRepository repository;
private final Scheduler scheduler;
public SchedulerRunner(PluginManager pluginManager, DataSetRepository repository, Scheduler scheduler)
{
this.pluginManager = pluginManager;
this.repository = repository;
this.scheduler = scheduler;
}
@Override
public void run(String... args)
{
log.info("Start scheduler initializer");
repository.findAllBySyncMode(SyncMode.TIMING)
.forEach(item -> {
log.info("Dataset [ {} ] will be scheduled", item.getName());
pluginManager.getPlugin(item.getScheduler())
.ifPresentOrElse(
plugin -> {
SchedulerRequest request = SchedulerRequest.builder()
.name(item.getCode())
.group("datacap")
.expression(item.getExpression())
.jobId(item.getCode())
.createBeforeDelete(true)
.build();
SchedulerService schedulerService = plugin.getService(SchedulerService.class);
if (item.getScheduler().equalsIgnoreCase("LocalScheduler")) {
request.setJob(new DatasetJob());
request.setScheduler(this.scheduler);
}
schedulerService.initialize(request);
},
() -> log.error("Scheduler [ {} ] not found", item.getScheduler())
);
});
log.info("End scheduler initializer");
}
}

View File

@ -1,62 +0,0 @@
package io.edurt.datacap.service.initializer;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.edurt.datacap.plugin.PluginManager;
import io.edurt.datacap.scheduler.SchedulerRequest;
import io.edurt.datacap.scheduler.SchedulerService;
import io.edurt.datacap.service.enums.SyncMode;
import io.edurt.datacap.service.initializer.job.DatasetJob;
import io.edurt.datacap.service.repository.DataSetRepository;
import io.edurt.datacap.service.service.DataSetService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Scheduler;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
public class DatasetSchedulerInitializer
implements CommandLineRunner
{
private final PluginManager pluginManager;
private final DataSetRepository repository;
private final DataSetService service;
private final Scheduler scheduler;
public DatasetSchedulerInitializer(PluginManager pluginManager, DataSetRepository repository, DataSetService service, Scheduler scheduler)
{
this.pluginManager = pluginManager;
this.repository = repository;
this.service = service;
this.scheduler = scheduler;
}
@Override
public void run(String... args)
throws Exception
{
log.info("Start dataset scheduler initializer");
this.repository.findAllBySyncMode(SyncMode.TIMING)
.forEach(item -> {
log.info("Dataset [ {} ] will be scheduled", item.getName());
pluginManager.getPlugin(item.getScheduler())
.ifPresent(scheduler -> {
SchedulerRequest request = new SchedulerRequest();
request.setName(item.getCode());
request.setGroup("datacap");
request.setExpression(item.getExpression());
request.setJobId(item.getCode());
request.setCreateBeforeDelete(true);
SchedulerService schedulerService = scheduler.getService(SchedulerService.class);
if (schedulerService.name().equals("Default")) {
request.setJob(new DatasetJob());
request.setScheduler(this.scheduler);
}
schedulerService.initialize(request);
});
});
log.info("End dataset scheduler initializer");
}
}

View File

@ -772,16 +772,17 @@ public class DataSetServiceImpl
log.info("Start schedule for dataset [ {} ] id [ {} ]", entity.getName(), entity.getId());
if (entity.getSyncMode().equals(SyncMode.TIMING)) {
pluginManager.getPlugin(entity.getScheduler())
.ifPresent(scheduler -> {
SchedulerRequest request = new SchedulerRequest();
request.setName(entity.getCode());
request.setGroup("datacap");
request.setExpression(entity.getExpression());
request.setJobId(entity.getCode());
request.setCreateBeforeDelete(true);
.ifPresent(plugin -> {
SchedulerRequest request = SchedulerRequest.builder()
.name(entity.getCode())
.group("datacap")
.expression(entity.getExpression())
.jobId(entity.getCode())
.createBeforeDelete(true)
.build();
SchedulerService schedulerService = scheduler.getService(SchedulerService.class);
if (schedulerService.name().equals("Default")) {
SchedulerService schedulerService = plugin.getService(SchedulerService.class);
if (entity.getScheduler().equalsIgnoreCase("LocalScheduler")) {
request.setJob(new DatasetJob());
request.setScheduler(this.scheduler);
}
@ -790,13 +791,14 @@ public class DataSetServiceImpl
}
else {
pluginManager.getPlugin(entity.getScheduler())
.ifPresent(scheduler -> {
SchedulerRequest request = new SchedulerRequest();
request.setName(entity.getCode());
request.setGroup("datacap");
.ifPresent(plugin -> {
SchedulerRequest request = SchedulerRequest.builder()
.name(entity.getCode())
.group("datacap")
.build();
SchedulerService schedulerService = scheduler.getService(SchedulerService.class);
if (schedulerService.name().equals("Default")) {
SchedulerService schedulerService = plugin.getService(SchedulerService.class);
if (entity.getScheduler().equalsIgnoreCase("LocalScheduler")) {
request.setScheduler(this.scheduler);
}
schedulerService.stop(request);

View File

@ -220,7 +220,7 @@
<ShadcnFormItem name="scheduler" :label="$t('common.scheduler')">
<ShadcnSelect v-model="formState.scheduler" name="scheduler">
<template #options>
<ShadcnSelectOption v-for="item in schedulers" :label="item" :value="item"/>
<ShadcnSelectOption v-for="item in schedulers" :label="item.name" :value="item.name"/>
</template>
</ShadcnSelect>
</ShadcnFormItem>

29
logo/scheduler/local.svg Normal file
View File

@ -0,0 +1,29 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
<!-- 背景圆形 -->
<!-- Background circle -->
<circle cx="120" cy="120" r="120" fill="#4A90E2" />
<!-- 计算机显示器主体 -->
<!-- Computer monitor body -->
<rect x="60" y="70" width="120" height="80" rx="4" fill="white" />
<!-- 显示器支架 -->
<!-- Monitor stand -->
<rect x="110" y="150" width="20" height="10" fill="white" />
<rect x="95" y="160" width="50" height="4" rx="2" fill="white" />
<!-- 时钟图案 -->
<!-- Clock pattern -->
<circle cx="120" cy="110" r="25" fill="#4A90E2" stroke="white" stroke-width="4" />
<line x1="120" y1="110" x2="120" y2="95" stroke="white" stroke-width="4" stroke-linecap="round" />
<line x1="120" y1="110" x2="130" y2="110" stroke="white" stroke-width="4" stroke-linecap="round" />
<!-- 齿轮装饰 -->
<!-- Gear decoration -->
<circle cx="170" cy="180" r="15" fill="white" />
<path d="M170,165 L173,180 L170,195 L167,180 Z" fill="#4A90E2" />
<path d="M155,180 L170,177 L185,180 L170,183 Z" fill="#4A90E2" />
<path d="M158,168 L172,178 L182,192 L168,182 Z" fill="#4A90E2" />
<path d="M158,192 L168,178 L182,168 L172,182 Z" fill="#4A90E2" />
<circle cx="170" cy="180" r="5" fill="#4A90E2" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -92,7 +92,7 @@
<!-- <module>parser/datacap-parser-trino</module>-->
<!-- <module>parser/datacap-parser-mysql</module>-->
<module>scheduler/datacap-scheduler-spi</module>
<!-- <module>scheduler/datacap-scheduler-local</module>-->
<module>scheduler/datacap-scheduler-local</module>
<module>notify/datacap-notify-spi</module>
<!-- <module>notify/datacap-notify-dingtalk</module>-->
<module>convert/datacap-convert-spi</module>
@ -106,6 +106,7 @@
<module>test/datacap-test-core</module>
<module>test/datacap-test-lib</module>
<module>test/datacap-test-executor</module>
<module>test/datacap-test-scheduler</module>
</modules>
<name>datacap</name>
@ -194,6 +195,7 @@
<useragent.version>1.21</useragent.version>
<openai.version>2024.01.3</openai.version>
<testcontainers.version>1.20.1</testcontainers.version>
<quartz.version>2.3.2</quartz.version>
<assembly-plugin.version>3.6.0</assembly-plugin.version>
<dep.reflections.version>0.10.2</dep.reflections.version>
<!-- datacap plugin dependency -->

View File

@ -1,17 +0,0 @@
package io.edurt.datacap.scheduler.local
import com.google.inject.multibindings.Multibinder
import io.edurt.datacap.scheduler.Scheduler
import io.edurt.datacap.scheduler.SchedulerModule
class LocalSchedulerModule : SchedulerModule() {
override fun name(): String {
return "Default"
}
override fun configure() {
Multibinder.newSetBinder(this.binder(), Scheduler::class.java)
.addBinding()
.to(LocalScheduler::class.java)
}
}

View File

@ -0,0 +1,12 @@
package io.edurt.datacap.scheduler.local
import io.edurt.datacap.plugin.Plugin
import io.edurt.datacap.plugin.PluginType
class LocalSchedulerPlugin : Plugin()
{
override fun getType(): PluginType
{
return PluginType.SCHEDULER
}
}

View File

@ -1,19 +1,18 @@
package io.edurt.datacap.scheduler.local
import io.edurt.datacap.scheduler.Scheduler
import io.edurt.datacap.scheduler.SchedulerRequest
import io.edurt.datacap.scheduler.SchedulerResponse
import io.edurt.datacap.scheduler.SchedulerService
class LocalScheduler : Scheduler {
override fun name(): String {
return "Default"
}
override fun initialize(request: SchedulerRequest): SchedulerResponse {
class LocalSchedulerService : SchedulerService
{
override fun initialize(request: SchedulerRequest): SchedulerResponse
{
return QuartzEndpoint.createJob(request)
}
override fun stop(request: SchedulerRequest): SchedulerResponse {
override fun stop(request: SchedulerRequest): SchedulerResponse
{
return QuartzEndpoint.removeJob(request)
}
}

View File

@ -5,19 +5,23 @@ import io.edurt.datacap.scheduler.SchedulerResponse
import org.quartz.*
import org.slf4j.LoggerFactory
object QuartzEndpoint {
object QuartzEndpoint
{
private val log = LoggerFactory.getLogger(this.javaClass)
@JvmStatic
fun createJob(request: SchedulerRequest): SchedulerResponse {
fun createJob(request: SchedulerRequest): SchedulerResponse
{
val response = SchedulerResponse()
val name = getJobName(request)
val group = getJobGroup(request)
try {
if (request.createBeforeDelete) {
try
{
if (request.createBeforeDelete)
{
val response = removeJob(request)
if (! response.successful) {
if (! response.successful)
{
throw IllegalArgumentException("Remove job failure " + response.message)
}
}
@ -40,14 +44,16 @@ object QuartzEndpoint {
log.info("Add new job [ {} ] to group [ {} ]", name, group)
scheduler.scheduleJob(jobDetail, trigger)
if (! scheduler.isStarted) {
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) {
catch (ex: Exception)
{
log.info("Add new job [ {} ] to group [ {} ] failure ", name, group, ex)
response.successful = false
response.message = ex.message
@ -56,11 +62,13 @@ object QuartzEndpoint {
}
@JvmStatic
fun removeJob(request: SchedulerRequest): SchedulerResponse {
fun removeJob(request: SchedulerRequest): SchedulerResponse
{
val response = SchedulerResponse()
val name = getJobName(request)
val group = getJobGroup(request)
try {
try
{
val scheduler: Scheduler = request.scheduler ?: throw IllegalArgumentException("Scheduler must not null")
log.info("Remove job [ {} ] from group [ {} ]", name, group)
@ -68,7 +76,8 @@ object QuartzEndpoint {
response.successful = true
log.info("Remove job [ {} ] from group [ {} ] successful", name, group)
}
catch (ex: Exception) {
catch (ex: Exception)
{
log.info("Remove job [ {} ] from group [ {} ] failure ", name, group, ex)
response.successful = false
response.message = ex.message
@ -76,11 +85,13 @@ object QuartzEndpoint {
return response
}
private fun getJobName(request: SchedulerRequest): String {
private fun getJobName(request: SchedulerRequest): String
{
return "job-${request.name}"
}
private fun getJobGroup(request: SchedulerRequest): String {
private fun getJobGroup(request: SchedulerRequest): String
{
return "job-group-${request.group}"
}
}

View File

@ -0,0 +1 @@
io.edurt.datacap.scheduler.local.LocalSchedulerPlugin

View File

@ -0,0 +1 @@
io.edurt.datacap.scheduler.local.LocalSchedulerService

View File

@ -1 +0,0 @@
io.edurt.datacap.scheduler.local.LocalSchedulerModule

View File

@ -1,28 +0,0 @@
package io.edurt.datacap.scheduler.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.scheduler.ScheduleManager
import io.edurt.datacap.scheduler.Scheduler
import org.junit.Before
import org.junit.Test
import kotlin.test.assertNotNull
class LocalSchedulerModuleTest {
private val name = "Local"
private var injector: Injector? = null
@Before
fun before() {
injector = Guice.createInjector(ScheduleManager())
}
@Test
fun test() {
val scheduler: Scheduler? = injector?.getInstance(Key.get(object : TypeLiteral<Set<Scheduler?>?>() {}))
?.first { v -> v?.name().equals(name) }
assertNotNull(scheduler)
}
}

View File

@ -11,10 +11,6 @@
<artifactId>datacap-scheduler-spi</artifactId>
<description>DataCap - Scheduler - Spi</description>
<properties>
<quartz.version>2.3.2</quartz.version>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>

View File

@ -6,7 +6,7 @@ import org.quartz.Job
@SuppressFBWarnings(value = ["EI_EXPOSE_REP2"])
data class SchedulerRequest(
var name: String? = null,
var group: String = "DataCap-Schedule-Group",
var group: String = "DataCap-Scheduler-Group",
var expression: String? = null,
var jobId: String? = null,
var job: Job? = null,
@ -23,7 +23,44 @@ data class SchedulerRequest(
private fun deepCopy(scheduler: org.quartz.Scheduler): org.quartz.Scheduler
{
// Implement the deep copy logic of the Scheduler object. The specific implementation depends on the type and structure of the Scheduler.
return scheduler
}
companion object
{
@JvmStatic
fun builder(): Builder
{
return Builder()
}
}
class Builder
{
private var name: String? = null
private var group: String = "DataCap-Schedule-Group"
private var expression: String? = null
private var jobId: String? = null
private var job: Job? = null
private var scheduler: org.quartz.Scheduler? = null
private var createBeforeDelete: Boolean = false
fun name(name: String?) = apply { this.name = name }
fun group(group: String) = apply { this.group = group }
fun expression(expression: String?) = apply { this.expression = expression }
fun jobId(jobId: String?) = apply { this.jobId = jobId }
fun job(job: Job?) = apply { this.job = job }
fun scheduler(scheduler: org.quartz.Scheduler?) = apply { this.scheduler = scheduler }
fun createBeforeDelete(createBeforeDelete: Boolean) = apply { this.createBeforeDelete = createBeforeDelete }
fun build() = SchedulerRequest(
name = name,
group = group,
expression = expression,
jobId = jobId,
job = job,
_scheduler = scheduler,
createBeforeDelete = createBeforeDelete
)
}
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.edurt.datacap</groupId>
<artifactId>datacap</artifactId>
<version>2024.4.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>datacap-test-scheduler</artifactId>
<description>DataCap - Test - Scheduler</description>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.edurt.datacap</groupId>
<artifactId>datacap-plugin</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.edurt.datacap</groupId>
<artifactId>datacap-scheduler-spi</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.edurt.datacap</groupId>
<artifactId>datacap-scheduler-local</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -3,8 +3,10 @@ package io.edurt.datacap.scheduler.local
import io.edurt.datacap.scheduler.SchedulerJob
import org.quartz.JobExecutionContext
class ExampleJob : SchedulerJob() {
override fun execute(p0: JobExecutionContext?) {
class ExampleJob : SchedulerJob()
{
override fun execute(p0: JobExecutionContext?)
{
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,30 @@
package io.edurt.datacap.test.local
import io.edurt.datacap.plugin.PluginConfigure
import io.edurt.datacap.plugin.PluginManager
import io.edurt.datacap.plugin.utils.PluginPathUtils
import org.junit.Assert.assertNotNull
import org.junit.Test
class LocalSchedulerModuleTest
{
private val pluginManager: PluginManager
private val pluginName = "LocalScheduler"
init
{
val projectRoot = PluginPathUtils.findProjectRoot()
val config = PluginConfigure.builder()
.pluginsDir(projectRoot.resolve("scheduler/datacap-scheduler-local"))
.build()
pluginManager = PluginManager(config).apply { start() }
}
@Test
fun test()
{
val plugin = pluginManager.getPlugin(pluginName)
assertNotNull(plugin.get())
}
}

View File

@ -3,28 +3,34 @@ package io.edurt.datacap.scheduler.local
import io.edurt.datacap.scheduler.SchedulerRequest
import org.junit.Before
import org.junit.Test
import org.quartz.impl.StdSchedulerFactory
import kotlin.test.assertTrue
class QuartzEndpointTest {
class QuartzEndpointTest
{
private val name: String = "TestJob"
private val group: String = "TestGroup"
private val request = SchedulerRequest()
@Before
fun before() {
fun before()
{
request.name = name
request.group = group
request.expression = "*/10 * * * * ?"
request.job = ExampleJob()
request.scheduler = StdSchedulerFactory.getDefaultScheduler()
}
@Test
fun testCreateJob() {
fun testCreateJob()
{
assertTrue(QuartzEndpoint.createJob(request).successful)
}
@Test
fun testRemoveJob() {
fun testRemoveJob()
{
QuartzEndpoint.createJob(request)
assertTrue(QuartzEndpoint.removeJob(request).successful)
}