⬆️ Upgrading dependencies. xxl-job 2.3.0 closed #I37WUG

This commit is contained in:
lengleng 2021-02-14 20:18:50 +08:00
parent 3c511d3b71
commit 50d1834352
168 changed files with 1435 additions and 815 deletions

View File

@ -7,110 +7,113 @@ use `pig_job`;
SET NAMES utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_cron` varchar(128) NOT NULL COMMENT '任务执行CRON',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态0-停止1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
PRIMARY KEY (`id`)
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态0-停止1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型0=自动注册、1=手动录入',
`address_list` varchar(512) DEFAULT NULL COMMENT '执行器地址列表,多地址逗号分隔',
PRIMARY KEY (`id`)
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限执行器ID列表多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限执行器ID列表多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL);
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_cron`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`, `trigger_status`, `trigger_last_time`, `trigger_next_time`) VALUES (1, 1, '0 0 0 * * ? *', '测试任务1', '2018-11-03 22:21:31', '2020-04-15 13:58:35', 'lengleng', '', 'ROUND', 'demoJobHandler', '', 'DISCARD_LATER', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '', 0, 0, 0);
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');

View File

@ -1,5 +1,7 @@
package com.pig4cloud.pig.common.job;
import java.util.stream.Collectors;
import com.pig4cloud.pig.common.job.properties.XxlJobProperties;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -9,8 +11,6 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import java.util.stream.Collectors;
/**
* xxl-job自动装配
*
@ -46,7 +46,7 @@ public class XxlJobAutoConfiguration {
xxlJobSpringExecutor.setLogRetentionDays(xxlJobProperties.getExecutor().getLogRetentionDays());
// 如果配置为空则获取注册中心的服务列表 "http://pigx-xxl:9080/xxl-job-admin"
if (StringUtils.isEmpty(xxlJobProperties.getAdmin().getAddresses())) {
if (!StringUtils.hasText(xxlJobProperties.getAdmin().getAddresses())) {
String serverList = discoveryClient.getServices().stream().filter(s -> s.contains(XXL_JOB_ADMIN))
.flatMap(s -> discoveryClient.getInstances(s).stream()).map(instance -> String
.format("http://%s:%s/%s", instance.getHost(), instance.getPort(), XXL_JOB_ADMIN))

View File

@ -28,7 +28,7 @@ public class XxlJobProperties implements InitializingBean, EnvironmentAware {
@Override
public void afterPropertiesSet() {
// 若是没有设置appname 则取 application Name
if (StringUtils.isEmpty(executor.getAppname())) {
if (!StringUtils.hasText(executor.getAppname())) {
executor.setAppname(environment.getProperty("spring.application.name"));
}
}

View File

@ -2,10 +2,12 @@ package com.xxl.job.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author xuxueli 2018-10-28 00:38:13
*/
@EnableDiscoveryClient
@SpringBootApplication
public class PigXxlJobAdminApplication {

View File

@ -70,14 +70,26 @@ public class JobGroupController {
if (xxlJobGroup.getAppname().length() < 4 || xxlJobGroup.getAppname().length() > 64) {
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length"));
}
if (xxlJobGroup.getAppname().contains(">") || xxlJobGroup.getAppname().contains("<")) {
return new ReturnT<String>(500, "AppName" + I18nUtil.getString("system_unvalid"));
}
if (xxlJobGroup.getTitle() == null || xxlJobGroup.getTitle().trim().length() == 0) {
return new ReturnT<String>(500,
(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")));
}
if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) {
return new ReturnT<String>(500,
I18nUtil.getString("jobgroup_field_title") + I18nUtil.getString("system_unvalid"));
}
if (xxlJobGroup.getAddressType() != 0) {
if (xxlJobGroup.getAddressList() == null || xxlJobGroup.getAddressList().trim().length() == 0) {
return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit"));
}
if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) {
return new ReturnT<String>(500,
I18nUtil.getString("jobgroup_field_registryList") + I18nUtil.getString("system_unvalid"));
}
String[] addresss = xxlJobGroup.getAddressList().split(",");
for (String item : addresss) {
if (item == null || item.trim().length() == 0) {
@ -86,6 +98,9 @@ public class JobGroupController {
}
}
// process
xxlJobGroup.setUpdateTime(new Date());
int ret = xxlJobGroupDao.save(xxlJobGroup);
return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
}
@ -131,6 +146,9 @@ public class JobGroupController {
}
}
// process
xxlJobGroup.setUpdateTime(new Date());
int ret = xxlJobGroupDao.update(xxlJobGroup);
return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
}

View File

@ -6,6 +6,9 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
import com.xxl.job.admin.core.thread.JobScheduleHelper;
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.admin.core.util.I18nUtil;
@ -16,6 +19,8 @@ import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
import com.xxl.job.core.glue.GlueTypeEnum;
import com.xxl.job.core.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@ -36,6 +41,8 @@ import java.util.*;
@RequestMapping("/jobinfo")
public class JobInfoController {
private static Logger logger = LoggerFactory.getLogger(JobInfoController.class);
@Resource
private XxlJobGroupDao xxlJobGroupDao;
@ -50,6 +57,8 @@ public class JobInfoController {
model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values()); // 路由策略-列表
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values()); // Glue类型-字典
model.addAttribute("ExecutorBlockStrategyEnum", ExecutorBlockStrategyEnum.values()); // 阻塞处理策略-字典
model.addAttribute("ScheduleTypeEnum", ScheduleTypeEnum.values()); // 调度类型
model.addAttribute("MisfireStrategyEnum", MisfireStrategyEnum.values()); // 调度过期策略
// 执行器列表
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
@ -151,13 +160,17 @@ public class JobInfoController {
@RequestMapping("/nextTriggerTime")
@ResponseBody
public ReturnT<List<String>> nextTriggerTime(String cron) {
public ReturnT<List<String>> nextTriggerTime(String scheduleType, String scheduleConf) {
XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
paramXxlJobInfo.setScheduleType(scheduleType);
paramXxlJobInfo.setScheduleConf(scheduleConf);
List<String> result = new ArrayList<>();
try {
CronExpression cronExpression = new CronExpression(cron);
Date lastTime = new Date();
for (int i = 0; i < 5; i++) {
lastTime = cronExpression.getNextValidTimeAfter(lastTime);
lastTime = JobScheduleHelper.generateNextValidTime(paramXxlJobInfo, lastTime);
if (lastTime != null) {
result.add(DateUtil.formatDateTime(lastTime));
}
@ -166,10 +179,13 @@ public class JobInfoController {
}
}
}
catch (ParseException e) {
return new ReturnT<List<String>>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid"));
catch (Exception e) {
logger.error(e.getMessage(), e);
return new ReturnT<List<String>>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")) + e.getMessage());
}
return new ReturnT<List<String>>(result);
}
}

View File

@ -1,6 +1,7 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.core.exception.XxlJobException;
import com.xxl.job.admin.core.complete.XxlJobCompleter;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
@ -196,7 +197,7 @@ public class JobLogController {
log.setHandleMsg(I18nUtil.getString("joblog_kill_log_byman") + ":"
+ (runResult.getMsg() != null ? runResult.getMsg() : ""));
log.setHandleTime(new Date());
xxlJobLogDao.updateHandleInfo(log);
XxlJobCompleter.updateHandleInfoAndFinish(log);
return new ReturnT<String>(runResult.getMsg());
}
else {

View File

@ -56,6 +56,13 @@ public class UserController {
List<XxlJobUser> list = xxlJobUserDao.pageList(start, length, username, role);
int list_count = xxlJobUserDao.pageListCount(start, length, username, role);
// filter
if (list != null && list.size() > 0) {
for (XxlJobUser item : list) {
item.setPassword(null);
}
}
// package result
Map<String, Object> maps = new HashMap<String, Object>();
maps.put("recordsTotal", list_count); // 总记录数

View File

@ -1,15 +1,16 @@
package com.xxl.job.admin.controller.interceptor;
import com.xxl.job.admin.core.util.FtlUtil;
import com.xxl.job.admin.core.util.I18nUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import java.util.HashMap;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import com.xxl.job.admin.core.util.FtlUtil;
import com.xxl.job.admin.core.util.I18nUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* push cookies to model as cookieMap
@ -17,7 +18,7 @@ import java.util.HashMap;
* @author xuxueli 2015-12-12 18:09:04
*/
@Component
public class CookieInterceptor extends HandlerInterceptorAdapter {
public class CookieInterceptor implements HandlerInterceptor {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@ -36,8 +37,6 @@ public class CookieInterceptor extends HandlerInterceptorAdapter {
if (modelAndView != null) {
modelAndView.addObject("I18nUtil", FtlUtil.generateStaticModel(I18nUtil.class.getName()));
}
super.postHandle(request, response, handler, modelAndView);
}
}

View File

@ -1,17 +1,18 @@
package com.xxl.job.admin.controller.interceptor;
import java.util.Arrays;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.service.LoginService;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* 权限拦截
@ -19,7 +20,7 @@ import java.util.Arrays;
* @author xuxueli 2015-12-12 18:09:04
*/
@Component
public class PermissionInterceptor extends HandlerInterceptorAdapter {
public class PermissionInterceptor implements HandlerInterceptor {
/**
* 针对 spring boot admin 对外暴露的接口
@ -34,11 +35,11 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
throws Exception {
if (!(handler instanceof HandlerMethod)) {
return super.preHandle(request, response, handler);
return true;
}
if (Arrays.stream(ACTUATOR_IGNORE).anyMatch(s -> request.getRequestURI().contains(s))) {
return super.preHandle(request, response, handler);
return true;
}
// if need login
@ -64,7 +65,7 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser);
}
return super.preHandle(request, response, handler);
return true;
}
}

View File

@ -1,11 +1,11 @@
package com.xxl.job.admin.controller.interceptor;
import javax.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* web mvc config
*

View File

@ -16,7 +16,6 @@ import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.core.biz.model.ReturnT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

View File

@ -0,0 +1,101 @@
package com.xxl.job.admin.core.complete;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.context.XxlJobContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
/**
* @author xuxueli 2020-10-30 20:43:10
*/
public class XxlJobCompleter {
private static Logger logger = LoggerFactory.getLogger(XxlJobCompleter.class);
/**
* common fresh handle entrance (limit only once)
* @param xxlJobLog
* @return
*/
public static int updateHandleInfoAndFinish(XxlJobLog xxlJobLog) {
// finish
finishJob(xxlJobLog);
// text最大64kb 避免长度过长
if (xxlJobLog.getHandleMsg().length() > 15000) {
xxlJobLog.setHandleMsg(xxlJobLog.getHandleMsg().substring(0, 15000));
}
// fresh handle
return XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateHandleInfo(xxlJobLog);
}
/**
* do somethind to finish job
*/
private static void finishJob(XxlJobLog xxlJobLog) {
// 1handle success, to trigger child job
String triggerChildMsg = null;
if (XxlJobContext.HANDLE_COCE_SUCCESS == xxlJobLog.getHandleCode()) {
XxlJobInfo xxlJobInfo = XxlJobAdminConfig.getAdminConfig().getXxlJobInfoDao()
.loadById(xxlJobLog.getJobId());
if (xxlJobInfo != null && xxlJobInfo.getChildJobId() != null
&& xxlJobInfo.getChildJobId().trim().length() > 0) {
triggerChildMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>"
+ I18nUtil.getString("jobconf_trigger_child_run") + "<<<<<<<<<<< </span><br>";
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
for (int i = 0; i < childJobIds.length; i++) {
int childJobId = (childJobIds[i] != null && childJobIds[i].trim().length() > 0
&& isNumeric(childJobIds[i])) ? Integer.valueOf(childJobIds[i]) : -1;
if (childJobId > 0) {
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);
ReturnT<String> triggerChildResult = ReturnT.SUCCESS;
// add msg
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg1"),
(i + 1), childJobIds.length, childJobIds[i],
(triggerChildResult.getCode() == ReturnT.SUCCESS_CODE
? I18nUtil.getString("system_success") : I18nUtil.getString("system_fail")),
triggerChildResult.getMsg());
}
else {
triggerChildMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg2"),
(i + 1), childJobIds.length, childJobIds[i]);
}
}
}
}
if (triggerChildMsg != null) {
xxlJobLog.setHandleMsg(xxlJobLog.getHandleMsg() + triggerChildMsg);
}
// 2fix_delay trigger next
// on the way
}
private static boolean isNumeric(String str) {
try {
int result = Integer.valueOf(str);
return true;
}
catch (NumberFormatException e) {
return false;
}
}
}

View File

@ -1,18 +1,23 @@
package com.xxl.job.admin.core.conf;
import java.util.Arrays;
import javax.annotation.Resource;
import javax.sql.DataSource;
import com.xxl.job.admin.core.alarm.JobAlarmer;
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
import com.xxl.job.admin.dao.*;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.dao.XxlJobLogDao;
import com.xxl.job.admin.dao.XxlJobLogReportDao;
import com.xxl.job.admin.dao.XxlJobRegistryDao;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;
/**
* xxl-job config
*

View File

@ -2,6 +2,7 @@ package com.xxl.job.admin.core.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
@ -19,6 +20,8 @@ public class XxlJobGroup {
private String addressList; // 执行器地址列表多地址逗号分隔(手动录入)
private Date updateTime;
// registry list
private List<String> registryList; // 执行器地址列表(系统注册)
@ -65,6 +68,14 @@ public class XxlJobGroup {
return addressList;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public void setAddressList(String addressList) {
this.addressList = addressList;
}

View File

@ -13,8 +13,6 @@ public class XxlJobInfo {
private int jobGroup; // 执行器主键ID
private String jobCron; // 任务执行CRON表达式
private String jobDesc;
private Date addTime;
@ -25,6 +23,12 @@ public class XxlJobInfo {
private String alarmEmail; // 报警邮件
private String scheduleType; // 调度类型
private String scheduleConf; // 调度配置值含义取决于调度类型
private String misfireStrategy; // 调度过期策略
private String executorRouteStrategy; // 执行器路由策略
private String executorHandler; // 执行器任务Handler名称
@ -69,14 +73,6 @@ public class XxlJobInfo {
this.jobGroup = jobGroup;
}
public String getJobCron() {
return jobCron;
}
public void setJobCron(String jobCron) {
this.jobCron = jobCron;
}
public String getJobDesc() {
return jobDesc;
}
@ -117,6 +113,30 @@ public class XxlJobInfo {
this.alarmEmail = alarmEmail;
}
public String getScheduleType() {
return scheduleType;
}
public void setScheduleType(String scheduleType) {
this.scheduleType = scheduleType;
}
public String getScheduleConf() {
return scheduleConf;
}
public void setScheduleConf(String scheduleConf) {
this.scheduleConf = scheduleConf;
}
public String getMisfireStrategy() {
return misfireStrategy;
}
public void setMisfireStrategy(String misfireStrategy) {
this.misfireStrategy = misfireStrategy;
}
public String getExecutorRouteStrategy() {
return executorRouteStrategy;
}

View File

@ -0,0 +1,39 @@
package com.xxl.job.admin.core.scheduler;
import com.xxl.job.admin.core.util.I18nUtil;
/**
* @author xuxueli 2020-10-29 21:11:23
*/
public enum MisfireStrategyEnum {
/**
* do nothing
*/
DO_NOTHING(I18nUtil.getString("misfire_strategy_do_nothing")),
/**
* fire once now
*/
FIRE_ONCE_NOW(I18nUtil.getString("misfire_strategy_fire_once_now"));
private String title;
MisfireStrategyEnum(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public static MisfireStrategyEnum match(String name, MisfireStrategyEnum defaultItem) {
for (MisfireStrategyEnum item : MisfireStrategyEnum.values()) {
if (item.name().equals(name)) {
return item;
}
}
return defaultItem;
}
}

View File

@ -0,0 +1,46 @@
package com.xxl.job.admin.core.scheduler;
import com.xxl.job.admin.core.util.I18nUtil;
/**
* @author xuxueli 2020-10-29 21:11:23
*/
public enum ScheduleTypeEnum {
NONE(I18nUtil.getString("schedule_type_none")),
/**
* schedule by cron
*/
CRON(I18nUtil.getString("schedule_type_cron")),
/**
* schedule by fixed rate (in seconds)
*/
FIX_RATE(I18nUtil.getString("schedule_type_fix_rate")),
/**
* schedule by fix delay (in seconds) after the last time
*/
/* FIX_DELAY(I18nUtil.getString("schedule_type_fix_delay")) */;
private String title;
ScheduleTypeEnum(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public static ScheduleTypeEnum match(String name, ScheduleTypeEnum defaultItem) {
for (ScheduleTypeEnum item : ScheduleTypeEnum.values()) {
if (item.name().equals(name)) {
return item;
}
}
return defaultItem;
}
}

View File

@ -24,22 +24,22 @@ public class XxlJobScheduler {
// init i18n
initI18n();
// admin trigger pool start
JobTriggerPoolHelper.toStart();
// admin registry monitor run
JobRegistryMonitorHelper.getInstance().start();
JobRegistryHelper.getInstance().start();
// admin fail-monitor run
JobFailMonitorHelper.getInstance().start();
// admin lose-monitor run
JobLosedMonitorHelper.getInstance().start();
// admin trigger pool start
JobTriggerPoolHelper.toStart();
// admin lose-monitor run ( depend on JobTriggerPoolHelper )
JobCompleteHelper.getInstance().start();
// admin log report start
JobLogReportHelper.getInstance().start();
// start-schedule
// start-schedule ( depend on JobTriggerPoolHelper )
JobScheduleHelper.getInstance().start();
logger.info(">>>>>>>>> init xxl-job admin success.");
@ -53,17 +53,17 @@ public class XxlJobScheduler {
// admin log report stop
JobLogReportHelper.getInstance().toStop();
// admin trigger pool stop
JobTriggerPoolHelper.toStop();
// admin lose-monitor stop
JobLosedMonitorHelper.getInstance().toStop();
JobCompleteHelper.getInstance().toStop();
// admin fail-monitor stop
JobFailMonitorHelper.getInstance().toStop();
// admin registry stop
JobRegistryMonitorHelper.getInstance().toStop();
JobRegistryHelper.getInstance().toStop();
// admin trigger pool stop
JobTriggerPoolHelper.toStop();
}

View File

@ -0,0 +1,192 @@
package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.complete.XxlJobCompleter;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.core.biz.model.HandleCallbackParam;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* job lose-monitor instance
*
* @author xuxueli 2015-9-1 18:05:56
*/
public class JobCompleteHelper {
private static Logger logger = LoggerFactory.getLogger(JobCompleteHelper.class);
private static JobCompleteHelper instance = new JobCompleteHelper();
public static JobCompleteHelper getInstance() {
return instance;
}
// ---------------------- monitor ----------------------
private ThreadPoolExecutor callbackThreadPool = null;
private Thread monitorThread;
private volatile boolean toStop = false;
public void start() {
// for callback
callbackThreadPool = new ThreadPoolExecutor(2, 20, 30L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(3000), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-job, admin JobLosedMonitorHelper-callbackThreadPool-" + r.hashCode());
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
logger.warn(
">>>>>>>>>>> xxl-job, callback too fast, match threadpool rejected handler(run now).");
}
});
// for monitor
monitorThread = new Thread(new Runnable() {
@Override
public void run() {
// wait for JobTriggerPoolHelper-init
try {
TimeUnit.MILLISECONDS.sleep(50);
}
catch (InterruptedException e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
// monitor
while (!toStop) {
try {
// 任务结果丢失处理调度记录停留在 "运行中" 状态超过10min且对应执行器心跳注册失败不在线则将本地调度主动标记失败
Date losedTime = DateUtil.addMinutes(new Date(), -10);
List<Long> losedJobIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao()
.findLostJobIds(losedTime);
if (losedJobIds != null && losedJobIds.size() > 0) {
for (Long logId : losedJobIds) {
XxlJobLog jobLog = new XxlJobLog();
jobLog.setId(logId);
jobLog.setHandleTime(new Date());
jobLog.setHandleCode(ReturnT.FAIL_CODE);
jobLog.setHandleMsg(I18nUtil.getString("joblog_lost_fail"));
XxlJobCompleter.updateHandleInfoAndFinish(jobLog);
}
}
}
catch (Exception e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
}
try {
TimeUnit.SECONDS.sleep(60);
}
catch (Exception e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, JobLosedMonitorHelper stop");
}
});
monitorThread.setDaemon(true);
monitorThread.setName("xxl-job, admin JobLosedMonitorHelper");
monitorThread.start();
}
public void toStop() {
toStop = true;
// stop registryOrRemoveThreadPool
callbackThreadPool.shutdownNow();
// stop monitorThread (interrupt and wait)
monitorThread.interrupt();
try {
monitorThread.join();
}
catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
// ---------------------- helper ----------------------
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
callbackThreadPool.execute(new Runnable() {
@Override
public void run() {
for (HandleCallbackParam handleCallbackParam : callbackParamList) {
ReturnT<String> callbackResult = callback(handleCallbackParam);
logger.debug(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
(callbackResult.getCode() == ReturnT.SUCCESS_CODE ? "success" : "fail"),
handleCallbackParam, callbackResult);
}
}
});
return ReturnT.SUCCESS;
}
private ReturnT<String> callback(HandleCallbackParam handleCallbackParam) {
// valid log item
XxlJobLog log = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().load(handleCallbackParam.getLogId());
if (log == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
}
if (log.getHandleCode() > 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback."); // avoid
// repeat
// callback,
// trigger
// child
// job
// etc
}
// handle msg
StringBuffer handleMsg = new StringBuffer();
if (log.getHandleMsg() != null) {
handleMsg.append(log.getHandleMsg()).append("<br>");
}
if (handleCallbackParam.getHandleMsg() != null) {
handleMsg.append(handleCallbackParam.getHandleMsg());
}
// success, save log
log.setHandleTime(new Date());
log.setHandleCode(handleCallbackParam.getHandleCode());
log.setHandleMsg(handleMsg.toString());
XxlJobCompleter.updateHandleInfoAndFinish(log);
return ReturnT.SUCCESS;
}
}

View File

@ -1,103 +0,0 @@
package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* job lose-monitor instance
*
* @author xuxueli 2015-9-1 18:05:56
*/
public class JobLosedMonitorHelper {
private static Logger logger = LoggerFactory.getLogger(JobLosedMonitorHelper.class);
private static JobLosedMonitorHelper instance = new JobLosedMonitorHelper();
public static JobLosedMonitorHelper getInstance() {
return instance;
}
// ---------------------- monitor ----------------------
private Thread monitorThread;
private volatile boolean toStop = false;
public void start() {
monitorThread = new Thread(new Runnable() {
@Override
public void run() {
// monitor
while (!toStop) {
try {
// 任务结果丢失处理调度记录停留在 "运行中" 状态超过10min且对应执行器心跳注册失败不在线则将本地调度主动标记失败
Date losedTime = DateUtil.addMinutes(new Date(), -10);
List<Long> losedJobIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao()
.findLostJobIds(losedTime);
if (losedJobIds != null && losedJobIds.size() > 0) {
for (Long logId : losedJobIds) {
XxlJobLog jobLog = new XxlJobLog();
jobLog.setId(logId);
jobLog.setHandleTime(new Date());
jobLog.setHandleCode(ReturnT.FAIL_CODE);
jobLog.setHandleMsg(I18nUtil.getString("joblog_lost_fail"));
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().updateHandleInfo(jobLog);
}
}
}
catch (Exception e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
}
try {
TimeUnit.SECONDS.sleep(60);
}
catch (Exception e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, JobLosedMonitorHelper stop");
}
});
monitorThread.setDaemon(true);
monitorThread.setName("xxl-job, admin JobLosedMonitorHelper");
monitorThread.start();
}
public void toStop() {
toStop = true;
// interrupt and wait
monitorThread.interrupt();
try {
monitorThread.join();
}
catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,215 @@
package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.core.biz.model.RegistryParam;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.enums.RegistryConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.concurrent.*;
/**
* job registry instance
*
* @author xuxueli 2016-10-02 19:10:24
*/
public class JobRegistryHelper {
private static Logger logger = LoggerFactory.getLogger(JobRegistryHelper.class);
private static JobRegistryHelper instance = new JobRegistryHelper();
public static JobRegistryHelper getInstance() {
return instance;
}
private ThreadPoolExecutor registryOrRemoveThreadPool = null;
private Thread registryMonitorThread;
private volatile boolean toStop = false;
public void start() {
// for registry or remove
registryOrRemoveThreadPool = new ThreadPoolExecutor(2, 10, 30L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(2000), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r,
"xxl-job, admin JobRegistryMonitorHelper-registryOrRemoveThreadPool-" + r.hashCode());
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
logger.warn(
">>>>>>>>>>> xxl-job, registry or remove too fast, match threadpool rejected handler(run now).");
}
});
// for monitor
registryMonitorThread = new Thread(new Runnable() {
@Override
public void run() {
while (!toStop) {
try {
// auto registry group
List<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao()
.findByAddressType(0);
if (groupList != null && !groupList.isEmpty()) {
// remove dead address (admin/executor)
List<Integer> ids = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao()
.findDead(RegistryConfig.DEAD_TIMEOUT, new Date());
if (ids != null && ids.size() > 0) {
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(ids);
}
// fresh online address (admin/executor)
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao()
.findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
if (list != null) {
for (XxlJobRegistry item : list) {
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
String appname = item.getRegistryKey();
List<String> registryList = appAddressMap.get(appname);
if (registryList == null) {
registryList = new ArrayList<String>();
}
if (!registryList.contains(item.getRegistryValue())) {
registryList.add(item.getRegistryValue());
}
appAddressMap.put(appname, registryList);
}
}
}
// fresh group address
for (XxlJobGroup group : groupList) {
List<String> registryList = appAddressMap.get(group.getAppname());
String addressListStr = null;
if (registryList != null && !registryList.isEmpty()) {
Collections.sort(registryList);
StringBuilder addressListSB = new StringBuilder();
for (String item : registryList) {
addressListSB.append(item).append(",");
}
addressListStr = addressListSB.toString();
addressListStr = addressListStr.substring(0, addressListStr.length() - 1);
}
group.setAddressList(addressListStr);
group.setUpdateTime(new Date());
XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
}
}
}
catch (Exception e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
}
}
try {
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
}
catch (InterruptedException e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, job registry monitor thread stop");
}
});
registryMonitorThread.setDaemon(true);
registryMonitorThread.setName("xxl-job, admin JobRegistryMonitorHelper-registryMonitorThread");
registryMonitorThread.start();
}
public void toStop() {
toStop = true;
// stop registryOrRemoveThreadPool
registryOrRemoveThreadPool.shutdownNow();
// stop monitir (interrupt and wait)
registryMonitorThread.interrupt();
try {
registryMonitorThread.join();
}
catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
// ---------------------- helper ----------------------
public ReturnT<String> registry(RegistryParam registryParam) {
// valid
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|| !StringUtils.hasText(registryParam.getRegistryKey())
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
}
// async execute
registryOrRemoveThreadPool.execute(new Runnable() {
@Override
public void run() {
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryUpdate(
registryParam.getRegistryGroup(), registryParam.getRegistryKey(),
registryParam.getRegistryValue(), new Date());
if (ret < 1) {
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registrySave(
registryParam.getRegistryGroup(), registryParam.getRegistryKey(),
registryParam.getRegistryValue(), new Date());
// fresh
freshGroupRegistryInfo(registryParam);
}
}
});
return ReturnT.SUCCESS;
}
public ReturnT<String> registryRemove(RegistryParam registryParam) {
// valid
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|| !StringUtils.hasText(registryParam.getRegistryKey())
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
}
// async execute
registryOrRemoveThreadPool.execute(new Runnable() {
@Override
public void run() {
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryDelete(
registryParam.getRegistryGroup(), registryParam.getRegistryKey(),
registryParam.getRegistryValue());
if (ret > 0) {
// fresh
freshGroupRegistryInfo(registryParam);
}
}
});
return ReturnT.SUCCESS;
}
private void freshGroupRegistryInfo(RegistryParam registryParam) {
// Under consideration, prevent affecting core tables
}
}

View File

@ -1,123 +0,0 @@
package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobRegistry;
import com.xxl.job.core.enums.RegistryConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* job registry instance
*
* @author xuxueli 2016-10-02 19:10:24
*/
public class JobRegistryMonitorHelper {
private static Logger logger = LoggerFactory.getLogger(JobRegistryMonitorHelper.class);
private static JobRegistryMonitorHelper instance = new JobRegistryMonitorHelper();
public static JobRegistryMonitorHelper getInstance() {
return instance;
}
private Thread registryThread;
private volatile boolean toStop = false;
public void start() {
registryThread = new Thread(new Runnable() {
@Override
public void run() {
while (!toStop) {
try {
// auto registry group
List<XxlJobGroup> groupList = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao()
.findByAddressType(0);
if (groupList != null && !groupList.isEmpty()) {
// remove dead address (admin/executor)
List<Integer> ids = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao()
.findDead(RegistryConfig.DEAD_TIMEOUT, new Date());
if (ids != null && ids.size() > 0) {
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().removeDead(ids);
}
// fresh online address (admin/executor)
HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
List<XxlJobRegistry> list = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao()
.findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
if (list != null) {
for (XxlJobRegistry item : list) {
if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
String appname = item.getRegistryKey();
List<String> registryList = appAddressMap.get(appname);
if (registryList == null) {
registryList = new ArrayList<String>();
}
if (!registryList.contains(item.getRegistryValue())) {
registryList.add(item.getRegistryValue());
}
appAddressMap.put(appname, registryList);
}
}
}
// fresh group address
for (XxlJobGroup group : groupList) {
List<String> registryList = appAddressMap.get(group.getAppname());
String addressListStr = null;
if (registryList != null && !registryList.isEmpty()) {
Collections.sort(registryList);
StringBuilder addressListSB = new StringBuilder();
for (String item : registryList) {
addressListSB.append(item).append(",");
}
addressListStr = addressListSB.toString();
addressListStr = addressListStr.substring(0, addressListStr.length() - 1);
}
group.setAddressList(addressListStr);
XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
}
}
}
catch (Exception e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
}
}
try {
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
}
catch (InterruptedException e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, job registry monitor thread stop");
}
});
registryThread.setDaemon(true);
registryThread.setName("xxl-job, admin JobRegistryMonitorHelper");
registryThread.start();
}
public void toStop() {
toStop = true;
// interrupt and wait
registryThread.interrupt();
try {
registryThread.join();
}
catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}

View File

@ -3,6 +3,8 @@ package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -10,7 +12,6 @@ import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@ -98,7 +99,18 @@ public class JobScheduleHelper {
// next-trigger-time
logger.warn(">>>>>>>>>>> xxl-job, schedule misfire, jobId = " + jobInfo.getId());
// fresh next
// 1misfire match
MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum
.match(jobInfo.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING);
if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) {
// FIRE_ONCE_NOW trigger
JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.MISFIRE, -1, null,
null, null);
logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = "
+ jobInfo.getId());
}
// 2fresh next
refreshNextValidTime(jobInfo, new Date());
}
@ -239,18 +251,18 @@ public class JobScheduleHelper {
@Override
public void run() {
// align second
try {
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
}
catch (InterruptedException e) {
if (!ringThreadToStop) {
logger.error(e.getMessage(), e);
}
}
while (!ringThreadToStop) {
// align second
try {
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
}
catch (InterruptedException e) {
if (!ringThreadToStop) {
logger.error(e.getMessage(), e);
}
}
try {
// second data
List<Integer> ringItemData = new ArrayList<>();
@ -280,16 +292,6 @@ public class JobScheduleHelper {
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
}
}
// next second, align second
try {
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
}
catch (InterruptedException e) {
if (!ringThreadToStop) {
logger.error(e.getMessage(), e);
}
}
}
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread stop");
}
@ -299,8 +301,8 @@ public class JobScheduleHelper {
ringThread.start();
}
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws ParseException {
Date nextValidTime = new CronExpression(jobInfo.getJobCron()).getNextValidTimeAfter(fromTime);
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
Date nextValidTime = generateNextValidTime(jobInfo, fromTime);
if (nextValidTime != null) {
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
jobInfo.setTriggerNextTime(nextValidTime.getTime());
@ -309,6 +311,9 @@ public class JobScheduleHelper {
jobInfo.setTriggerStatus(0);
jobInfo.setTriggerLastTime(0);
jobInfo.setTriggerNextTime(0);
logger.warn(
">>>>>>>>>>> xxl-job, refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}",
jobInfo.getId(), jobInfo.getScheduleType(), jobInfo.getScheduleConf());
}
}
@ -388,4 +393,21 @@ public class JobScheduleHelper {
logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper stop");
}
// ---------------------- tools ----------------------
public static Date generateNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
if (ScheduleTypeEnum.CRON == scheduleTypeEnum) {
Date nextValidTime = new CronExpression(jobInfo.getScheduleConf()).getNextValidTimeAfter(fromTime);
return nextValidTime;
}
else if (ScheduleTypeEnum.FIX_RATE == scheduleTypeEnum /*
* || ScheduleTypeEnum.
* FIX_DELAY ==
* scheduleTypeEnum
*/) {
return new Date(fromTime.getTime() + Integer.valueOf(jobInfo.getScheduleConf()) * 1000);
}
return null;
}
}

View File

@ -13,7 +13,8 @@ public enum TriggerTypeEnum {
I18nUtil.getString("jobconf_trigger_type_cron")), RETRY(
I18nUtil.getString("jobconf_trigger_type_retry")), PARENT(
I18nUtil.getString("jobconf_trigger_type_parent")), API(
I18nUtil.getString("jobconf_trigger_type_api"));
I18nUtil.getString("jobconf_trigger_type_api")), MISFIRE(
I18nUtil.getString("jobconf_trigger_type_misfire"));
private TriggerTypeEnum(String title) {
this.title = title;

View File

@ -1,27 +1,13 @@
package com.xxl.job.admin.service.impl;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.dao.XxlJobLogDao;
import com.xxl.job.admin.dao.XxlJobRegistryDao;
import com.xxl.job.admin.core.thread.JobCompleteHelper;
import com.xxl.job.admin.core.thread.JobRegistryHelper;
import com.xxl.job.core.biz.AdminBiz;
import com.xxl.job.core.biz.model.HandleCallbackParam;
import com.xxl.job.core.biz.model.RegistryParam;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
/**
@ -30,162 +16,19 @@ import java.util.List;
@Service
public class AdminBizImpl implements AdminBiz {
private static Logger logger = LoggerFactory.getLogger(AdminBizImpl.class);
@Resource
public XxlJobLogDao xxlJobLogDao;
@Resource
private XxlJobInfoDao xxlJobInfoDao;
@Resource
private XxlJobRegistryDao xxlJobRegistryDao;
@Resource
private XxlJobGroupDao xxlJobGroupDao;
@Override
public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
for (HandleCallbackParam handleCallbackParam : callbackParamList) {
ReturnT<String> callbackResult = callback(handleCallbackParam);
logger.debug(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
(callbackResult.getCode() == IJobHandler.SUCCESS.getCode() ? "success" : "fail"),
handleCallbackParam, callbackResult);
}
return ReturnT.SUCCESS;
}
private ReturnT<String> callback(HandleCallbackParam handleCallbackParam) {
// valid log item
XxlJobLog log = xxlJobLogDao.load(handleCallbackParam.getLogId());
if (log == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
}
if (log.getHandleCode() > 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback."); // avoid
// repeat
// callback,
// trigger
// child
// job
// etc
}
// trigger success, to trigger child job
String callbackMsg = null;
if (IJobHandler.SUCCESS.getCode() == handleCallbackParam.getExecuteResult().getCode()) {
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(log.getJobId());
if (xxlJobInfo != null && xxlJobInfo.getChildJobId() != null
&& xxlJobInfo.getChildJobId().trim().length() > 0) {
callbackMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>"
+ I18nUtil.getString("jobconf_trigger_child_run") + "<<<<<<<<<<< </span><br>";
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
for (int i = 0; i < childJobIds.length; i++) {
int childJobId = (childJobIds[i] != null && childJobIds[i].trim().length() > 0
&& isNumeric(childJobIds[i])) ? Integer.valueOf(childJobIds[i]) : -1;
if (childJobId > 0) {
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);
ReturnT<String> triggerChildResult = ReturnT.SUCCESS;
// add msg
callbackMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg1"), (i + 1),
childJobIds.length, childJobIds[i],
(triggerChildResult.getCode() == ReturnT.SUCCESS_CODE
? I18nUtil.getString("system_success") : I18nUtil.getString("system_fail")),
triggerChildResult.getMsg());
}
else {
callbackMsg += MessageFormat.format(I18nUtil.getString("jobconf_callback_child_msg2"), (i + 1),
childJobIds.length, childJobIds[i]);
}
}
}
}
// handle msg
StringBuffer handleMsg = new StringBuffer();
if (log.getHandleMsg() != null) {
handleMsg.append(log.getHandleMsg()).append("<br>");
}
if (handleCallbackParam.getExecuteResult().getMsg() != null) {
handleMsg.append(handleCallbackParam.getExecuteResult().getMsg());
}
if (callbackMsg != null) {
handleMsg.append(callbackMsg);
}
if (handleMsg.length() > 15000) {
handleMsg = new StringBuffer(handleMsg.substring(0, 15000)); // text最大64kb
// 避免长度过长
}
// success, save log
log.setHandleTime(new Date());
log.setHandleCode(handleCallbackParam.getExecuteResult().getCode());
log.setHandleMsg(handleMsg.toString());
xxlJobLogDao.updateHandleInfo(log);
return ReturnT.SUCCESS;
}
private boolean isNumeric(String str) {
try {
int result = Integer.valueOf(str);
return true;
}
catch (NumberFormatException e) {
return false;
}
return JobCompleteHelper.getInstance().callback(callbackParamList);
}
@Override
public ReturnT<String> registry(RegistryParam registryParam) {
// valid
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|| !StringUtils.hasText(registryParam.getRegistryKey())
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
}
int ret = xxlJobRegistryDao.registryUpdate(registryParam.getRegistryGroup(), registryParam.getRegistryKey(),
registryParam.getRegistryValue(), new Date());
if (ret < 1) {
xxlJobRegistryDao.registrySave(registryParam.getRegistryGroup(), registryParam.getRegistryKey(),
registryParam.getRegistryValue(), new Date());
// fresh
freshGroupRegistryInfo(registryParam);
}
return ReturnT.SUCCESS;
return JobRegistryHelper.getInstance().registry(registryParam);
}
@Override
public ReturnT<String> registryRemove(RegistryParam registryParam) {
// valid
if (!StringUtils.hasText(registryParam.getRegistryGroup())
|| !StringUtils.hasText(registryParam.getRegistryKey())
|| !StringUtils.hasText(registryParam.getRegistryValue())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "Illegal Argument.");
}
int ret = xxlJobRegistryDao.registryDelete(registryParam.getRegistryGroup(), registryParam.getRegistryKey(),
registryParam.getRegistryValue());
if (ret > 0) {
// fresh
freshGroupRegistryInfo(registryParam);
}
return ReturnT.SUCCESS;
}
private void freshGroupRegistryInfo(RegistryParam registryParam) {
// Under consideration, prevent affecting core tables
return JobRegistryHelper.getInstance().registryRemove(registryParam);
}
}

View File

@ -1,10 +1,12 @@
package com.xxl.job.admin.service.impl;
import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.core.model.XxlJobLogReport;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
import com.xxl.job.admin.core.thread.JobScheduleHelper;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.dao.*;
@ -19,7 +21,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.*;
/**
@ -67,15 +68,13 @@ public class XxlJobServiceImpl implements XxlJobService {
@Override
public ReturnT<String> add(XxlJobInfo jobInfo) {
// valid
// valid base
XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());
if (group == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("system_please_choose") + I18nUtil.getString("jobinfo_field_jobgroup")));
}
if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid"));
}
if (jobInfo.getJobDesc() == null || jobInfo.getJobDesc().trim().length() == 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_jobdesc")));
@ -84,14 +83,40 @@ public class XxlJobServiceImpl implements XxlJobService {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_author")));
}
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
// valid trigger
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
if (scheduleTypeEnum == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_executorRouteStrategy") + I18nUtil.getString("system_unvalid")));
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_executorBlockStrategy") + I18nUtil.getString("system_unvalid")));
if (scheduleTypeEnum == ScheduleTypeEnum.CRON) {
if (jobInfo.getScheduleConf() == null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "Cron" + I18nUtil.getString("system_unvalid"));
}
}
else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE/*
* || scheduleTypeEnum ==
* ScheduleTypeEnum.
* FIX_DELAY
*/) {
if (jobInfo.getScheduleConf() == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")));
}
try {
int fixSecond = Integer.valueOf(jobInfo.getScheduleConf());
if (fixSecond < 1) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
}
catch (Exception e) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
}
// valid job
if (GlueTypeEnum.match(jobInfo.getGlueType()) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_gluetype") + I18nUtil.getString("system_unvalid")));
@ -100,13 +125,26 @@ public class XxlJobServiceImpl implements XxlJobService {
&& (jobInfo.getExecutorHandler() == null || jobInfo.getExecutorHandler().trim().length() == 0)) {
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input") + "JobHandler"));
}
// fix "\r" in shell
// fix "\r" in shell
if (GlueTypeEnum.GLUE_SHELL == GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource() != null) {
jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("\r", ""));
}
// ChildJobId valid
// valid advanced
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_executorRouteStrategy") + I18nUtil.getString("system_unvalid")));
}
if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("misfire_strategy") + I18nUtil.getString("system_unvalid")));
}
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_executorBlockStrategy") + I18nUtil.getString("system_unvalid")));
}
// ChildJobId valid
if (jobInfo.getChildJobId() != null && jobInfo.getChildJobId().trim().length() > 0) {
String[] childJobIds = jobInfo.getChildJobId().split(",");
for (String childJobIdItem : childJobIds) {
@ -161,10 +199,7 @@ public class XxlJobServiceImpl implements XxlJobService {
@Override
public ReturnT<String> update(XxlJobInfo jobInfo) {
// valid
if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_unvalid"));
}
// valid base
if (jobInfo.getJobDesc() == null || jobInfo.getJobDesc().trim().length() == 0) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_jobdesc")));
@ -173,16 +208,55 @@ public class XxlJobServiceImpl implements XxlJobService {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_field_author")));
}
// valid trigger
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null);
if (scheduleTypeEnum == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
if (scheduleTypeEnum == ScheduleTypeEnum.CRON) {
if (jobInfo.getScheduleConf() == null || !CronExpression.isValidExpression(jobInfo.getScheduleConf())) {
return new ReturnT<String>(ReturnT.FAIL_CODE, "Cron" + I18nUtil.getString("system_unvalid"));
}
}
else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE /*
* || scheduleTypeEnum ==
* ScheduleTypeEnum.
* FIX_DELAY
*/) {
if (jobInfo.getScheduleConf() == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
try {
int fixSecond = Integer.valueOf(jobInfo.getScheduleConf());
if (fixSecond < 1) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
}
catch (Exception e) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
}
// valid advanced
if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_executorRouteStrategy") + I18nUtil.getString("system_unvalid")));
}
if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("misfire_strategy") + I18nUtil.getString("system_unvalid")));
}
if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("jobinfo_field_executorBlockStrategy") + I18nUtil.getString("system_unvalid")));
}
// ChildJobId valid
// ChildJobId valid
if (jobInfo.getChildJobId() != null && jobInfo.getChildJobId().trim().length() > 0) {
String[] childJobIds = jobInfo.getChildJobId().split(",");
for (String childJobIdItem : childJobIds) {
@ -227,27 +301,32 @@ public class XxlJobServiceImpl implements XxlJobService {
// next trigger time (5s后生效避开预读周期)
long nextTriggerTime = exists_jobInfo.getTriggerNextTime();
if (exists_jobInfo.getTriggerStatus() == 1 && !jobInfo.getJobCron().equals(exists_jobInfo.getJobCron())) {
boolean scheduleDataNotChanged = jobInfo.getScheduleType().equals(exists_jobInfo.getScheduleType())
&& jobInfo.getScheduleConf().equals(exists_jobInfo.getScheduleConf());
if (exists_jobInfo.getTriggerStatus() == 1 && !scheduleDataNotChanged) {
try {
Date nextValidTime = new CronExpression(jobInfo.getJobCron())
.getNextValidTimeAfter(new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
Date nextValidTime = JobScheduleHelper.generateNextValidTime(jobInfo,
new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
if (nextValidTime == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_never_fire"));
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
nextTriggerTime = nextValidTime.getTime();
}
catch (ParseException e) {
catch (Exception e) {
logger.error(e.getMessage(), e);
return new ReturnT<String>(ReturnT.FAIL_CODE,
I18nUtil.getString("jobinfo_field_cron_unvalid") + " | " + e.getMessage());
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
}
exists_jobInfo.setJobGroup(jobInfo.getJobGroup());
exists_jobInfo.setJobCron(jobInfo.getJobCron());
exists_jobInfo.setJobDesc(jobInfo.getJobDesc());
exists_jobInfo.setAuthor(jobInfo.getAuthor());
exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail());
exists_jobInfo.setScheduleType(jobInfo.getScheduleType());
exists_jobInfo.setScheduleConf(jobInfo.getScheduleConf());
exists_jobInfo.setMisfireStrategy(jobInfo.getMisfireStrategy());
exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy());
exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler());
exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());
@ -280,20 +359,27 @@ public class XxlJobServiceImpl implements XxlJobService {
public ReturnT<String> start(int id) {
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
// valid
ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(xxlJobInfo.getScheduleType(), ScheduleTypeEnum.NONE);
if (ScheduleTypeEnum.NONE == scheduleTypeEnum) {
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type_none_limit_start")));
}
// next trigger time (5s后生效避开预读周期)
long nextTriggerTime = 0;
try {
Date nextValidTime = new CronExpression(xxlJobInfo.getJobCron())
.getNextValidTimeAfter(new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
Date nextValidTime = JobScheduleHelper.generateNextValidTime(xxlJobInfo,
new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS));
if (nextValidTime == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("jobinfo_field_cron_never_fire"));
return new ReturnT<String>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
nextTriggerTime = nextValidTime.getTime();
}
catch (ParseException e) {
catch (Exception e) {
logger.error(e.getMessage(), e);
return new ReturnT<String>(ReturnT.FAIL_CODE,
I18nUtil.getString("jobinfo_field_cron_unvalid") + " | " + e.getMessage());
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")));
}
xxlJobInfo.setTriggerStatus(1);

View File

@ -20,8 +20,6 @@ spring:
password: ${MYSQL-PWD:root}
mvc:
static-path-pattern: /static/**
resources:
static-locations: classpath:/static/
freemarker:
suffix: .ftl
request-context-attribute: request

View File

@ -1,6 +1,6 @@
admin_name=Scheduling Center
admin_name_full=Distributed Task Scheduling Platform XXL-JOB
admin_version=2.2.1-SNAPSHOT
admin_version=2.3.0
admin_i18n=en
## system
@ -117,8 +117,6 @@ jobinfo_field_jobdesc=Job description
jobinfo_field_timeout=Job timeout period
jobinfo_field_gluetype=GLUE Type
jobinfo_field_executorparam=Param
jobinfo_field_cron_unvalid=The Cron is illegal
jobinfo_field_cron_never_fire=The Cron will never fire
jobinfo_field_author=Author
jobinfo_field_alarmemail=Alarm email
jobinfo_field_alarmemail_placeholder=Please enter alarm mail, if there are more than one comma separated
@ -144,6 +142,19 @@ jobinfo_glue_rollback=Version Backtrack
jobinfo_glue_jobid_unvalid=Job ID is illegal
jobinfo_glue_gluetype_unvalid=The job is not GLUE Type
jobinfo_field_executorTimeout_placeholder=Job Timeout periodin seconds. effect if greater than zero
schedule_type=Schedule Type
schedule_type_none=None
schedule_type_cron=Cron
schedule_type_fix_rate=Fix rate
schedule_type_fix_delay=Fix delay
schedule_type_none_limit_start=The current schedule type disables startup
misfire_strategy=Misfire strategy
misfire_strategy_do_nothing=Do nothing
misfire_strategy_fire_once_now=Fire once now
jobinfo_conf_base=Base configuration
jobinfo_conf_schedule=Schedule configuration
jobinfo_conf_job=Job configuration
jobinfo_conf_advanced=Advanced configuration
## job log
joblog_name=Trigger Log
@ -243,6 +254,7 @@ jobconf_trigger_type_manual=Manual trigger
jobconf_trigger_type_parent=Parent job trigger
jobconf_trigger_type_api=Api trigger
jobconf_trigger_type_retry=Fail retry trigger
jobconf_trigger_type_misfire=Misfire compensation trigger
## user
user_manage=User Manage

View File

@ -1,6 +1,6 @@
admin_name=任务调度中心
admin_name_full=分布式任务调度平台XXL-JOB
admin_version=2.2.1-SNAPSHOT
admin_version=2.3.0
admin_i18n=
## system
@ -116,8 +116,6 @@ jobinfo_field_jobgroup=执行器
jobinfo_field_jobdesc=任务描述
jobinfo_field_gluetype=运行模式
jobinfo_field_executorparam=任务参数
jobinfo_field_cron_unvalid=Cron格式非法
jobinfo_field_cron_never_fire=Cron非法永远不会触发
jobinfo_field_author=负责人
jobinfo_field_timeout=任务超时时间
jobinfo_field_alarmemail=报警邮件
@ -144,6 +142,19 @@ jobinfo_glue_rollback=版本回溯
jobinfo_glue_jobid_unvalid=任务ID非法
jobinfo_glue_gluetype_unvalid=该任务非GLUE模式
jobinfo_field_executorTimeout_placeholder=任务超时时间,单位秒,大于零时生效
schedule_type=调度类型
schedule_type_none=
schedule_type_cron=CRON
schedule_type_fix_rate=固定速度
schedule_type_fix_delay=固定延迟
schedule_type_none_limit_start=当前调度类型禁止启动
misfire_strategy=调度过期策略
misfire_strategy_do_nothing=忽略
misfire_strategy_fire_once_now=立即执行一次
jobinfo_conf_base=基础配置
jobinfo_conf_schedule=调度配置
jobinfo_conf_job=任务配置
jobinfo_conf_advanced=高级配置
## job log
joblog_name=调度日志
@ -243,6 +254,7 @@ jobconf_trigger_type_manual=手动触发
jobconf_trigger_type_parent=父任务触发
jobconf_trigger_type_api=API触发
jobconf_trigger_type_retry=失败重试触发
jobconf_trigger_type_misfire=调度过期补偿
## user
user_manage=用户管理

View File

@ -1,6 +1,6 @@
admin_name=任務調度中心
admin_name_full=分布式任務調度平臺XXL-JOB
admin_version=2.2.1-SNAPSHOT
admin_version=2.3.0
admin_i18n=
## system
@ -116,8 +116,6 @@ jobinfo_field_jobgroup=執行器
jobinfo_field_jobdesc=任務描述
jobinfo_field_gluetype=運行模式
jobinfo_field_executorparam=任務參數
jobinfo_field_cron_unvalid=Cron 格式非法
jobinfo_field_cron_never_fire=Cron 格式非法,永遠不會觸發
jobinfo_field_author=負責人
jobinfo_field_timeout=任務超時秒數
jobinfo_field_alarmemail=告警郵件
@ -144,6 +142,19 @@ jobinfo_glue_rollback=版本回復
jobinfo_glue_jobid_unvalid=任務ID非法
jobinfo_glue_gluetype_unvalid=該任務非GLUE模式
jobinfo_field_executorTimeout_placeholder=任務超時時間,單位秒,大於零時生效
schedule_type=調度類型
schedule_type_none=
schedule_type_cron=CRON
schedule_type_fix_rate=固定速度
schedule_type_fix_delay=固定延遲
schedule_type_none_limit_start=當前調度類型禁止啟動
misfire_strategy=調度過期策略
misfire_strategy_do_nothing=忽略
misfire_strategy_fire_once_now=立即執行壹次
jobinfo_conf_base=基礎配置
jobinfo_conf_schedule=調度配置
jobinfo_conf_job=任務配置
jobinfo_conf_advanced=高級配置
## job log
joblog_name=調度日誌
@ -243,6 +254,7 @@ jobconf_trigger_type_manual=手動觸發
jobconf_trigger_type_parent=父任務觸發
jobconf_trigger_type_api=API觸發
jobconf_trigger_type_retry=失敗重試觸發
jobconf_trigger_type_misfire=調度過期補償
## user
user_manage=用户管理

View File

@ -9,6 +9,7 @@
<result column="title" property="title" />
<result column="address_type" property="addressType" />
<result column="address_list" property="addressList" />
<result column="update_time" property="updateTime" />
</resultMap>
<sql id="Base_Column_List">
@ -16,7 +17,8 @@
t.app_name,
t.title,
t.address_type,
t.address_list
t.address_list,
t.update_time
</sql>
<select id="findAll" resultMap="XxlJobGroup">
@ -33,8 +35,8 @@
</select>
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" useGeneratedKeys="true" keyProperty="id" >
INSERT INTO xxl_job_group ( `app_name`, `title`, `address_type`, `address_list`)
values ( #{appname}, #{title}, #{addressType}, #{addressList});
INSERT INTO xxl_job_group ( `app_name`, `title`, `address_type`, `address_list`, `update_time`)
values ( #{appname}, #{title}, #{addressType}, #{addressList}, #{updateTime} );
</insert>
<update id="update" parameterType="com.xxl.job.admin.core.model.XxlJobGroup" >
@ -42,7 +44,8 @@
SET `app_name` = #{appname},
`title` = #{title},
`address_type` = #{addressType},
`address_list` = #{addressList}
`address_list` = #{addressList},
`update_time` = #{updateTime}
WHERE id = #{id}
</update>

View File

@ -7,7 +7,6 @@
<result column="id" property="id" />
<result column="job_group" property="jobGroup" />
<result column="job_cron" property="jobCron" />
<result column="job_desc" property="jobDesc" />
<result column="add_time" property="addTime" />
@ -16,6 +15,10 @@
<result column="author" property="author" />
<result column="alarm_email" property="alarmEmail" />
<result column="schedule_type" property="scheduleType" />
<result column="schedule_conf" property="scheduleConf" />
<result column="misfire_strategy" property="misfireStrategy" />
<result column="executor_route_strategy" property="executorRouteStrategy" />
<result column="executor_handler" property="executorHandler" />
<result column="executor_param" property="executorParam" />
@ -38,12 +41,14 @@
<sql id="Base_Column_List">
t.id,
t.job_group,
t.job_cron,
t.job_desc,
t.add_time,
t.update_time,
t.author,
t.alarm_email,
t.schedule_type,
t.schedule_conf,
t.misfire_strategy,
t.executor_route_strategy,
t.executor_handler,
t.executor_param,
@ -109,12 +114,14 @@
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" >
INSERT INTO xxl_job_info (
job_group,
job_cron,
job_desc,
add_time,
update_time,
author,
alarm_email,
schedule_type,
schedule_conf,
misfire_strategy,
executor_route_strategy,
executor_handler,
executor_param,
@ -131,12 +138,14 @@
trigger_next_time
) VALUES (
#{jobGroup},
#{jobCron},
#{jobDesc},
#{addTime},
#{updateTime},
#{author},
#{alarmEmail},
#{scheduleType},
#{scheduleConf},
#{misfireStrategy},
#{executorRouteStrategy},
#{executorHandler},
#{executorParam},
@ -168,11 +177,13 @@
UPDATE xxl_job_info
SET
job_group = #{jobGroup},
job_cron = #{jobCron},
job_desc = #{jobDesc},
update_time = #{updateTime},
author = #{author},
alarm_email = #{alarmEmail},
schedule_type = #{scheduleType},
schedule_conf = #{scheduleConf},
misfire_strategy = #{misfireStrategy},
executor_route_strategy = #{executorRouteStrategy},
executor_handler = #{executorHandler},
executor_param = #{executorParam},

View File

@ -247,15 +247,27 @@
</update>
<select id="findLostJobIds" resultType="long" >
SELECT t.id
FROM xxl_job_log AS t
WHERE t.trigger_code = 200
and t.handle_code = 0
and t.trigger_time <![CDATA[ <= ]]> #{losedTime}
and t.executor_address not in (
SELECT t2.registry_value
FROM xxl_job_registry AS t2
)
SELECT
t.id
FROM
xxl_job_log t
LEFT JOIN xxl_job_registry t2 ON t.executor_address = t2.registry_value
WHERE
t.trigger_code = 200
AND t.handle_code = 0
AND t.trigger_time <![CDATA[ <= ]]> #{losedTime}
AND t2.id IS NULL;
</select>
<!--
SELECT t.id
FROM xxl_job_log AS t
WHERE t.trigger_code = 200
and t.handle_code = 0
and t.trigger_time <![CDATA[ <= ]]> #{losedTime}
and t.executor_address not in (
SELECT t2.registry_value
FROM xxl_job_registry AS t2
)
-->
</mapper>

View File

Before

Width:  |  Height:  |  Size: 326 KiB

After

Width:  |  Height:  |  Size: 326 KiB

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Some files were not shown because too many files have changed in this diff Show More