diff --git a/backend/pom.xml b/backend/pom.xml
index 8cfbd29b81..34721c92c4 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -162,9 +162,15 @@
- org.quartz-scheduler
- quartz
- 2.3.0
+ com.fit2cloud
+ quartz-spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
+
+ 0.0.4
@@ -288,5 +294,43 @@
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/libs-milestone
+
+ false
+
+
+
+ jcenter-snapshots
+ jcenter
+ https://jcenter.bintray.com/
+
+
+ fit2cloud-enterprise-release
+ Fit2Cloud Enterprise Release
+ http://repository.fit2cloud.com/content/repositories/fit2cloud-enterprise-release/
+
+ true
+
+
+ true
+
+
+
+ fit2cloud
+ fit2cloud
+ http://repository.fit2cloud.com/content/groups/public/
+
+ true
+
+
+ true
+
+
+
+
\ No newline at end of file
diff --git a/backend/src/main/java/io/metersphere/Application.java b/backend/src/main/java/io/metersphere/Application.java
index 730b148045..33f41bce49 100644
--- a/backend/src/main/java/io/metersphere/Application.java
+++ b/backend/src/main/java/io/metersphere/Application.java
@@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.PropertySource;
+import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication(exclude = {QuartzAutoConfiguration.class})
@ServletComponentScan
@@ -15,6 +16,7 @@ import org.springframework.context.annotation.PropertySource;
KafkaProperties.class,
JmeterProperties.class
})
+@EnableScheduling
@PropertySource(value = {"file:/opt/metersphere/conf/metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
public class Application {
public static void main(String[] args) {
diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java
index ad2ef1c8b3..2d7f0dfa57 100644
--- a/backend/src/main/java/io/metersphere/api/service/APITestService.java
+++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java
@@ -14,35 +14,24 @@ import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.constants.ScheduleType;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
-import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator;
-import io.metersphere.job.QuartzManager;
import io.metersphere.job.sechedule.ApiTestJob;
-import io.metersphere.job.sechedule.PerformanceTestJob;
import io.metersphere.service.FileService;
import io.metersphere.service.ScheduleService;
-import org.apache.commons.lang3.StringUtils;
-import org.quartz.JobDataMap;
-import org.quartz.JobKey;
-import org.quartz.SchedulerException;
-import org.quartz.TriggerKey;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
-
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
-import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.stream.Collectors;
@Service
diff --git a/backend/src/main/java/io/metersphere/config/QuartzAutoConfiguration.java b/backend/src/main/java/io/metersphere/config/QuartzAutoConfiguration.java
new file mode 100644
index 0000000000..38b219d4f5
--- /dev/null
+++ b/backend/src/main/java/io/metersphere/config/QuartzAutoConfiguration.java
@@ -0,0 +1,93 @@
+package io.metersphere.config;
+
+import com.fit2cloud.autoconfigure.QuartzProperties;
+import com.fit2cloud.quartz.QuartzInstanceIdGenerator;
+import com.fit2cloud.quartz.SchedulerStarter;
+import com.fit2cloud.quartz.service.QuartzManageService;
+import com.fit2cloud.quartz.util.QuartzBeanFactory;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+import org.springframework.util.StringUtils;
+
+import javax.sql.DataSource;
+import java.util.Properties;
+import java.util.TimeZone;
+
+@Configuration
+@EnableConfigurationProperties(QuartzProperties.class)
+@ConditionalOnClass(DataSource.class)
+@AutoConfigureAfter(DataSource.class)
+public class QuartzAutoConfiguration {
+ private DataSource dataSource;
+
+ private QuartzProperties properties;
+
+ public QuartzAutoConfiguration(ObjectProvider dataSourceProvider, QuartzProperties properties) {
+ this.dataSource = dataSourceProvider.getIfAvailable();
+ this.properties = properties;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true")
+ public SchedulerStarter schedulerStarter() {
+ return new SchedulerStarter();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true")
+ public QuartzBeanFactory quartzBeanFactory() {
+ return new QuartzBeanFactory();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true")
+ public QuartzManageService quartzManageService() {
+ return new QuartzManageService();
+ }
+
+ @Bean
+ @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true")
+ public TimeZone quartzTimeZone() {
+ return TimeZone.getTimeZone(properties.getTimeZone());
+ }
+
+ @Bean
+ @ConditionalOnClass(DataSource.class)
+ @ConditionalOnProperty(prefix = "quartz", value = "enabled", havingValue = "true")
+ public SchedulerFactoryBean clusterSchedulerFactoryBean() {
+ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
+ schedulerFactoryBean.setDataSource(this.dataSource);
+ schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContextKey");
+ schedulerFactoryBean.setOverwriteExistingJobs(true);
+ schedulerFactoryBean.setStartupDelay(60);// 60 秒之后开始执行定时任务
+ Properties props = new Properties();
+ props.put("org.quartz.scheduler.instanceName", "clusterScheduler");
+ props.put("org.quartz.scheduler.instanceId", "AUTO"); // 集群下的instanceId 必须唯一
+ props.put("org.quartz.scheduler.instanceIdGenerator.class", QuartzInstanceIdGenerator.class.getName());// instanceId 生成的方式
+ props.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
+ props.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
+ props.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+ props.put("org.quartz.jobStore.isClustered", "true");
+ props.put("org.quartz.jobStore.clusterCheckinInterval", "20000");
+ props.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+ props.put("org.quartz.threadPool.threadCount", "10");
+ props.put("org.quartz.threadPool.threadPriority", "5");
+ props.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");
+ schedulerFactoryBean.setQuartzProperties(props);
+ if (!StringUtils.isEmpty(this.properties.getSchedulerName())) {
+ schedulerFactoryBean.setBeanName(this.properties.getSchedulerName());
+ }
+ return schedulerFactoryBean;
+ }
+}
diff --git a/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java b/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java
index 44f731893c..bb4ce5bcb0 100644
--- a/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java
+++ b/backend/src/main/java/io/metersphere/job/sechedule/ApiTestJob.java
@@ -5,10 +5,10 @@ import io.metersphere.api.service.APITestService;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CommonBeanFactory;
-import io.metersphere.commons.utils.LogUtil;
-import io.metersphere.job.QuartzManager;
-import org.apache.commons.lang3.StringUtils;
-import org.quartz.*;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobKey;
+import org.quartz.TriggerKey;
+
public class ApiTestJob extends MsScheduleJob {
@@ -19,12 +19,7 @@ public class ApiTestJob extends MsScheduleJob {
}
@Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- if (StringUtils.isBlank(resourceId)) {
- QuartzManager.removeJob(getJobKey(resourceId), getTriggerKey(resourceId));
- }
- LogUtil.info("ApiTestSchedule Running: " + resourceId);
- LogUtil.info("CronExpression: " + expression);
+ void businessExecute(JobExecutionContext context) {
SaveAPITestRequest request = new SaveAPITestRequest();
request.setId(resourceId);
request.setUserId(userId);
diff --git a/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java b/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java
index 3e947d2bdd..2ddaff0345 100644
--- a/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java
+++ b/backend/src/main/java/io/metersphere/job/sechedule/MsScheduleJob.java
@@ -1,8 +1,9 @@
package io.metersphere.job.sechedule;
-import org.quartz.Job;
+import io.metersphere.commons.utils.LogUtil;
+import org.quartz.*;
-public abstract class MsScheduleJob implements Job{
+public abstract class MsScheduleJob implements Job {
protected String resourceId;
@@ -10,15 +11,19 @@ public abstract class MsScheduleJob implements Job{
protected String expression;
- public void setResourceId(String resourceId) {
- this.resourceId = resourceId;
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+
+ JobKey jobKey = context.getTrigger().getJobKey();
+ JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
+ this.resourceId = jobDataMap.getString("resourceId");
+ this.userId = jobDataMap.getString("userId");
+ this.expression = jobDataMap.getString("expression");
+
+ LogUtil.info(jobKey.getGroup()+ " Running: " + resourceId);
+ LogUtil.info("CronExpression: " + expression);
+ businessExecute(context);
}
- public void setExpression(String expression) {
- this.expression = expression;
- }
-
- public void setUserId(String userId) {
- this.userId = userId;
- }
+ abstract void businessExecute(JobExecutionContext context);
}
diff --git a/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java b/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java
index 0ef58506e3..e17daeae0c 100644
--- a/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java
+++ b/backend/src/main/java/io/metersphere/job/sechedule/PerformanceTestJob.java
@@ -3,13 +3,9 @@ package io.metersphere.job.sechedule;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CommonBeanFactory;
-import io.metersphere.commons.utils.LogUtil;
-import io.metersphere.job.QuartzManager;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.track.request.testplan.RunTestPlanRequest;
-import org.apache.commons.lang3.StringUtils;
import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
@@ -22,18 +18,12 @@ public class PerformanceTestJob extends MsScheduleJob {
}
@Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- if (StringUtils.isBlank(resourceId)) {
- QuartzManager.removeJob(getJobKey(resourceId), getTriggerKey(resourceId));
- }
- LogUtil.info("PerformanceTestSchedule Running: " + resourceId);
- LogUtil.info("CronExpression: " + expression);
+ void businessExecute(JobExecutionContext context) {
RunTestPlanRequest request = new RunTestPlanRequest();
request.setId(resourceId);
request.setUserId(userId);
request.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
performanceTestService.run(request);
-
}
public static JobKey getJobKey(String testId) {
diff --git a/backend/src/main/java/io/metersphere/job/QuartzManager.java b/backend/src/main/java/io/metersphere/job/sechedule/ScheduleManager.java
similarity index 69%
rename from backend/src/main/java/io/metersphere/job/QuartzManager.java
rename to backend/src/main/java/io/metersphere/job/sechedule/ScheduleManager.java
index a3d9ff42ab..9fd2aaa882 100644
--- a/backend/src/main/java/io/metersphere/job/QuartzManager.java
+++ b/backend/src/main/java/io/metersphere/job/sechedule/ScheduleManager.java
@@ -1,12 +1,16 @@
-package io.metersphere.job;
+package io.metersphere.job.sechedule;
import io.metersphere.commons.utils.LogUtil;
import org.quartz.*;
-import org.quartz.impl.StdSchedulerFactory;
+import org.springframework.stereotype.Component;
-public class QuartzManager {
+import javax.annotation.Resource;
- public static StdSchedulerFactory sf = new StdSchedulerFactory();
+@Component
+public class ScheduleManager {
+
+ @Resource
+ private Scheduler scheduler;
/**
* 添加 simpleJob
@@ -17,24 +21,28 @@ public class QuartzManager {
* @param jobDataMap
* @throws SchedulerException
*/
- public static void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class extends Job> cls, int repeatIntervalTime,
- JobDataMap jobDataMap) throws SchedulerException {
+ public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class extends Job> cls, int repeatIntervalTime,
+ JobDataMap jobDataMap) throws SchedulerException {
- Scheduler sched = sf.getScheduler();
+ JobBuilder jobBuilder = JobBuilder.newJob(cls).withIdentity(jobKey);
- JobDetail jd = JobBuilder.newJob(cls).withIdentity(jobKey).setJobData(jobDataMap).build();
+ if (jobDataMap != null) {
+ jobBuilder.usingJobData(jobDataMap);
+ }
+
+ JobDetail jd = jobBuilder.build();
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
.withSchedule(
SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(repeatIntervalTime).repeatForever())
.startNow().build();
- sched.scheduleJob(jd, trigger);
+ scheduler.scheduleJob(jd, trigger);
try {
- if (!sched.isShutdown()) {
- sched.start();
+ if (!scheduler.isShutdown()) {
+ scheduler.start();
}
} catch (SchedulerException e) {
@@ -44,8 +52,8 @@ public class QuartzManager {
}
}
- public static void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class extends Job> cls, int repeatIntervalTime) throws SchedulerException {
- addSimpleJob(jobKey, triggerKey, cls, repeatIntervalTime);
+ public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class extends Job> cls, int repeatIntervalTime) throws SchedulerException {
+ addSimpleJob(jobKey, triggerKey, cls, repeatIntervalTime);
}
/**
@@ -56,11 +64,14 @@ public class QuartzManager {
* @param cron
* @param jobDataMap
*/
- public static void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) {
+ public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) {
try {
+
+ LogUtil.info("addCronJob: " + triggerKey.getName() + "," + triggerKey.getGroup());
+
JobBuilder jobBuilder = JobBuilder.newJob(jobClass).withIdentity(jobKey);
if (jobDataMap != null) {
- jobBuilder.setJobData(jobDataMap);
+ jobBuilder.usingJobData(jobDataMap);
}
JobDetail jobDetail = jobBuilder.build();
@@ -74,12 +85,10 @@ public class QuartzManager {
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
- Scheduler sched = sf.getScheduler();
+ scheduler.scheduleJob(jobDetail, trigger);
- sched.scheduleJob(jobDetail, trigger);
-
- if (!sched.isShutdown()) {
- sched.start();
+ if (!scheduler.isShutdown()) {
+ scheduler.start();
}
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
@@ -87,7 +96,7 @@ public class QuartzManager {
}
}
- public static void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) {
+ public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) {
addCronJob(jobKey, triggerKey, jobClass, cron, null);
}
@@ -97,14 +106,12 @@ public class QuartzManager {
* @param cron
* @throws SchedulerException
*/
- public static void modifyCronJobTime(TriggerKey triggerKey, String cron) throws SchedulerException {
-
- Scheduler sched = sf.getScheduler();
+ public void modifyCronJobTime(TriggerKey triggerKey, String cron) throws SchedulerException {
LogUtil.info("modifyCronJobTime: " + triggerKey.getName() + "," + triggerKey.getGroup());
try {
- CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
+ CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
@@ -125,7 +132,7 @@ public class QuartzManager {
trigger = (CronTrigger) triggerBuilder.build();// 创建Trigger对象
- sched.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间
+ scheduler.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间
/** 方式一 :调用 rescheduleJob 结束 */
/** 方式二:先删除,然后在创建一个新的Job */
@@ -146,15 +153,13 @@ public class QuartzManager {
* @param repeatIntervalTime
* @throws SchedulerException
*/
- public static void modifySimpleJobTime(TriggerKey triggerKey, int repeatIntervalTime) throws SchedulerException {
-
- Scheduler sched = sf.getScheduler();
+ public void modifySimpleJobTime(TriggerKey triggerKey, int repeatIntervalTime) throws SchedulerException {
try {
LogUtil.info("modifySimpleJobTime: " + triggerKey.getName() + "," + triggerKey.getGroup());
- SimpleTrigger trigger = (SimpleTrigger) sched.getTrigger(triggerKey);
+ SimpleTrigger trigger = (SimpleTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
@@ -175,7 +180,7 @@ public class QuartzManager {
trigger = (SimpleTrigger) triggerBuilder.build();// 创建Trigger对象
- sched.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间
+ scheduler.rescheduleJob(triggerKey, trigger);// 修改一个任务的触发时间
/** 方式一 :调用 rescheduleJob 结束 */
@@ -201,19 +206,17 @@ public class QuartzManager {
* @param jobKey
* @param triggerKey
*/
- public static void removeJob(JobKey jobKey, TriggerKey triggerKey) {
+ public void removeJob(JobKey jobKey, TriggerKey triggerKey) {
try {
LogUtil.info("RemoveJob: " + jobKey.getName() + "," + jobKey.getGroup());
- Scheduler sched = sf.getScheduler();
+ scheduler.pauseTrigger(triggerKey);
- sched.pauseTrigger(triggerKey);
+ scheduler.unscheduleJob(triggerKey);
- sched.unscheduleJob(triggerKey);
-
- sched.deleteJob(jobKey);
+ scheduler.deleteJob(jobKey);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
@@ -232,7 +235,7 @@ public class QuartzManager {
}
- public static void shutdownJobs(Scheduler sched) {
+ public void shutdownJobs(Scheduler sched) {
try {
if (!sched.isShutdown()) {
sched.shutdown();
@@ -252,12 +255,10 @@ public class QuartzManager {
* @param jobDataMap
* @throws SchedulerException
*/
- public static void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz,
- int intervalTime, JobDataMap jobDataMap) throws SchedulerException {
+ public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz,
+ int intervalTime, JobDataMap jobDataMap) throws SchedulerException {
- Scheduler sched = sf.getScheduler();
-
- if (sched.checkExists(triggerKey)) {
+ if (scheduler.checkExists(triggerKey)) {
modifySimpleJobTime(triggerKey, intervalTime);
} else {
addSimpleJob(jobKey, triggerKey, clz, intervalTime, jobDataMap);
@@ -265,7 +266,7 @@ public class QuartzManager {
}
- public static void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, int intervalTime) throws SchedulerException {
+ public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, int intervalTime) throws SchedulerException {
addOrUpdateSimpleJob(jobKey, triggerKey, clz, intervalTime, null);
}
@@ -279,23 +280,22 @@ public class QuartzManager {
* @param jobDataMap
* @throws SchedulerException
*/
- public static void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) throws SchedulerException {
- Scheduler sched = sf.getScheduler();
+ public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, JobDataMap jobDataMap) throws SchedulerException {
LogUtil.info("AddOrUpdateCronJob: " + jobKey.getName() + "," + triggerKey.getGroup());
- if (sched.checkExists(triggerKey)) {
+ if (scheduler.checkExists(triggerKey)) {
modifyCronJobTime(triggerKey, cron);
} else {
addCronJob(jobKey, triggerKey, jobClass, cron, jobDataMap);
}
}
- public static void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) throws SchedulerException {
+ public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron) throws SchedulerException {
addOrUpdateCronJob(jobKey, triggerKey, jobClass, cron, null);
}
- public static JobDataMap getDefaultJobDataMap(String resourceId, String expression, String userId) {
+ public JobDataMap getDefaultJobDataMap(String resourceId, String expression, String userId) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("resourceId", resourceId);
jobDataMap.put("expression", expression);
diff --git a/backend/src/main/java/io/metersphere/service/ScheduleService.java b/backend/src/main/java/io/metersphere/service/ScheduleService.java
index d15becdeca..4ddb050080 100644
--- a/backend/src/main/java/io/metersphere/service/ScheduleService.java
+++ b/backend/src/main/java/io/metersphere/service/ScheduleService.java
@@ -4,13 +4,10 @@ import com.alibaba.fastjson.JSON;
import io.metersphere.base.domain.Schedule;
import io.metersphere.base.domain.ScheduleExample;
import io.metersphere.base.mapper.ScheduleMapper;
-import io.metersphere.commons.constants.ScheduleGroup;
-import io.metersphere.commons.constants.ScheduleType;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
-import io.metersphere.job.QuartzManager;
-import io.metersphere.job.sechedule.ApiTestJob;
+import io.metersphere.job.sechedule.ScheduleManager;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobKey;
import org.quartz.SchedulerException;
@@ -28,6 +25,8 @@ public class ScheduleService {
@Resource
private ScheduleMapper scheduleMapper;
+ @Resource
+ private ScheduleManager scheduleManager;
public void addSchedule(Schedule schedule) {
schedule.setId(UUID.randomUUID().toString());
@@ -73,11 +72,10 @@ public class ScheduleService {
try {
if (schedule.getEnable()) {
LogUtil.error("初始化任务:" + JSON.toJSONString(schedule));
- QuartzManager.addOrUpdateCronJob(new JobKey(schedule.getKey(), schedule.getGroup()),
+ scheduleManager.addOrUpdateCronJob(new JobKey(schedule.getKey(), schedule.getGroup()),
new TriggerKey(schedule.getKey(), schedule.getGroup()), Class.forName(schedule.getJob()), schedule.getValue(),
- QuartzManager.getDefaultJobDataMap(schedule.getResourceId(), schedule.getValue(), schedule.getUserId()));
+ scheduleManager.getDefaultJobDataMap(schedule.getResourceId(), schedule.getValue(), schedule.getUserId()));
}
- Thread.sleep(1*60*1000);
} catch (Exception e) {
LogUtil.error("初始化任务失败", e);
e.printStackTrace();
@@ -100,14 +98,14 @@ public class ScheduleService {
String cronExpression = request.getValue();
if (enable != null && enable && StringUtils.isNotBlank(cronExpression)) {
try {
- QuartzManager.addOrUpdateCronJob(jobKey, triggerKey, clazz, cronExpression, QuartzManager.getDefaultJobDataMap(request.getResourceId(), cronExpression, SessionUtils.getUser().getId()));
+ scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, clazz, cronExpression, scheduleManager.getDefaultJobDataMap(request.getResourceId(), cronExpression, SessionUtils.getUser().getId()));
} catch (SchedulerException e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException("定时任务开启异常");
}
} else {
try {
- QuartzManager.removeJob(jobKey, triggerKey);
+ scheduleManager.removeJob(jobKey, triggerKey);
} catch (Exception e) {
MSException.throwException("定时任务关闭异常");
}
diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties
index 2afe88e538..1729fe9d3a 100644
--- a/backend/src/main/resources/application.properties
+++ b/backend/src/main/resources/application.properties
@@ -64,4 +64,8 @@ kafka.ssl.provider=
kafka.ssl.truststore-type=
# jmeter
-jmeter.home=/opt/jmeter
\ No newline at end of file
+jmeter.home=/opt/jmeter
+
+# quartz
+quartz.enabled=true
+quartz.scheduler-name=msServerJob
\ No newline at end of file
diff --git a/backend/src/main/resources/db/migration/V5__schedule.sql b/backend/src/main/resources/db/migration/V5__schedule.sql
index 449a53f4dd..2d7302148a 100644
--- a/backend/src/main/resources/db/migration/V5__schedule.sql
+++ b/backend/src/main/resources/db/migration/V5__schedule.sql
@@ -1,3 +1,155 @@
+-- quartz start
+CREATE TABLE `qrtz_job_details` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `JOB_NAME` varchar(200) NOT NULL,
+ `JOB_GROUP` varchar(200) NOT NULL,
+ `DESCRIPTION` varchar(250) DEFAULT NULL,
+ `JOB_CLASS_NAME` varchar(250) NOT NULL,
+ `IS_DURABLE` varchar(1) NOT NULL,
+ `IS_NONCONCURRENT` varchar(1) NOT NULL,
+ `IS_UPDATE_DATA` varchar(1) NOT NULL,
+ `REQUESTS_RECOVERY` varchar(1) NOT NULL,
+ `JOB_DATA` blob,
+ PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
+ KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
+ KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_triggers` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `TRIGGER_NAME` varchar(200) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ `JOB_NAME` varchar(200) NOT NULL,
+ `JOB_GROUP` varchar(200) NOT NULL,
+ `DESCRIPTION` varchar(250) DEFAULT NULL,
+ `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
+ `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
+ `PRIORITY` int(11) DEFAULT NULL,
+ `TRIGGER_STATE` varchar(16) NOT NULL,
+ `TRIGGER_TYPE` varchar(8) NOT NULL,
+ `START_TIME` bigint(13) NOT NULL,
+ `END_TIME` bigint(13) DEFAULT NULL,
+ `CALENDAR_NAME` varchar(200) DEFAULT NULL,
+ `MISFIRE_INSTR` smallint(2) DEFAULT NULL,
+ `JOB_DATA` blob,
+ PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
+ KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
+ KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
+ KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
+ KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
+ KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
+ KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
+ KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
+ KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
+ KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
+ KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
+ KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
+ CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_blob_triggers` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `TRIGGER_NAME` varchar(200) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ `BLOB_DATA` blob,
+ PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_calendars` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `CALENDAR_NAME` varchar(200) NOT NULL,
+ `CALENDAR` blob NOT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_cron_triggers` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `TRIGGER_NAME` varchar(200) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ `CRON_EXPRESSION` varchar(120) NOT NULL,
+ `TIME_ZONE_ID` varchar(80) DEFAULT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_fired_triggers` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `ENTRY_ID` varchar(95) NOT NULL,
+ `TRIGGER_NAME` varchar(200) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ `INSTANCE_NAME` varchar(200) NOT NULL,
+ `FIRED_TIME` bigint(13) NOT NULL,
+ `SCHED_TIME` bigint(13) NOT NULL,
+ `PRIORITY` int(11) NOT NULL,
+ `STATE` varchar(16) NOT NULL,
+ `JOB_NAME` varchar(200) DEFAULT NULL,
+ `JOB_GROUP` varchar(200) DEFAULT NULL,
+ `IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
+ `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
+ KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
+ KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
+ KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
+ KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
+ KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_locks` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `LOCK_NAME` varchar(40) NOT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_paused_trigger_grps` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_scheduler_state` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `INSTANCE_NAME` varchar(200) NOT NULL,
+ `LAST_CHECKIN_TIME` bigint(13) NOT NULL,
+ `CHECKIN_INTERVAL` bigint(13) NOT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_simple_triggers` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `TRIGGER_NAME` varchar(200) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ `REPEAT_COUNT` bigint(7) NOT NULL,
+ `REPEAT_INTERVAL` bigint(12) NOT NULL,
+ `TIMES_TRIGGERED` bigint(10) NOT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE `qrtz_simprop_triggers` (
+ `SCHED_NAME` varchar(120) NOT NULL,
+ `TRIGGER_NAME` varchar(200) NOT NULL,
+ `TRIGGER_GROUP` varchar(200) NOT NULL,
+ `STR_PROP_1` varchar(512) DEFAULT NULL,
+ `STR_PROP_2` varchar(512) DEFAULT NULL,
+ `STR_PROP_3` varchar(512) DEFAULT NULL,
+ `INT_PROP_1` int(11) DEFAULT NULL,
+ `INT_PROP_2` int(11) DEFAULT NULL,
+ `LONG_PROP_1` bigint(20) DEFAULT NULL,
+ `LONG_PROP_2` bigint(20) DEFAULT NULL,
+ `DEC_PROP_1` decimal(13,4) DEFAULT NULL,
+ `DEC_PROP_2` decimal(13,4) DEFAULT NULL,
+ `BOOL_PROP_1` varchar(1) DEFAULT NULL,
+ `BOOL_PROP_2` varchar(1) DEFAULT NULL,
+ PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
+ CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- quartz end
+
CREATE TABLE IF NOT EXISTS `schedule` (
`id` varchar(50) NOT NULL COMMENT 'Schedule ID',
`key` varchar(50) NOT NULL COMMENT 'Schedule Key',