重要功能推送:支持子任务依赖;

v1.4
xueli.xue 8 years ago
parent 34c54e5586
commit 8048b0c78c

@ -161,6 +161,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (
`glue_switch` int(11) DEFAULT '0' COMMENT 'GLUE模式开关0-否1-是',
`glue_source` text COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`child_jobkey` varchar(255) DEFAULT NULL COMMENT '子任务Key',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

@ -41,19 +41,20 @@ public class JobInfoController {
@RequestMapping("/add")
@ResponseBody
public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc, String author, String alarmEmail,
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark) {
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark,
String childJobKey) {
return xxlJobService.add(jobGroup, jobCron, jobDesc, author, alarmEmail,
executorAddress, executorHandler, executorParam, glueSwitch, glueSource, glueRemark);
executorAddress, executorHandler, executorParam, glueSwitch, glueSource, glueRemark, childJobKey);
}
@RequestMapping("/reschedule")
@ResponseBody
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
String executorAddress, String executorHandler, String executorParam, int glueSwitch) {
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String childJobKey) {
return xxlJobService.reschedule(jobGroup, jobName, jobCron, jobDesc, author, alarmEmail,
executorAddress, executorHandler, executorParam, glueSwitch);
executorAddress, executorHandler, executorParam, glueSwitch, childJobKey);
}
@RequestMapping("/remove")

@ -1,23 +1,31 @@
package com.xxl.job.admin.core.callback;
import com.xxl.job.admin.core.model.ReturnT;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.util.DynamicSchedulerUtil;
import com.xxl.job.core.router.model.RequestModel;
import com.xxl.job.core.router.model.ResponseModel;
import com.xxl.job.core.util.XxlJobNetCommUtil;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
/**
* Created by xuxueli on 2016-5-22 11:15:42
*/
public class XxlJobLogCallbackServerHandler extends AbstractHandler {
private static Logger logger = LoggerFactory.getLogger(XxlJobLogCallbackServerHandler.class);
@Override
public void handle(String s, Request baseRequest, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
@ -33,6 +41,31 @@ public class XxlJobLogCallbackServerHandler extends AbstractHandler {
ResponseModel responseModel = null;
XxlJobLog log = DynamicSchedulerUtil.xxlJobLogDao.load(requestModel.getLogId());
if (log!=null) {
// trigger success, to trigger child job, and avoid repeat trigger child job
if (!ResponseModel.SUCCESS.equals(log.getHandleStatus())) {
XxlJobInfo xxlJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) {
String[] jobKeyArr = xxlJobInfo.getChildJobKey().split("_");
if (jobKeyArr!=null && jobKeyArr.length==2) {
XxlJobInfo childJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKeyArr[0], jobKeyArr[1]);
if (childJobInfo!=null) {
try {
boolean ret = DynamicSchedulerUtil.triggerJob(childJobInfo.getJobName(), childJobInfo.getJobGroup());
// add msg
String msg = requestModel.getMsg();
msg += MessageFormat.format("<br> 触发子任务执行, jobKey:{0}, status:{1}, 描述:{2}", xxlJobInfo.getChildJobKey(), ret, childJobInfo.getJobDesc());
requestModel.setMsg(msg);
} catch (SchedulerException e) {
logger.error("", e);
}
}
}
}
}
// save log
log.setHandleTime(new Date());
log.setHandleStatus(requestModel.getStatus());
log.setHandleMsg(requestModel.getMsg());

@ -29,6 +29,8 @@ public class XxlJobInfo {
private String glueSource; // GLUE源代码
private String glueRemark; // GLUE备注
private String childJobKey; // 子任务Key
// copy from quartz
private String jobStatus; // 任务状态 【base on quartz】
@ -152,6 +154,14 @@ public class XxlJobInfo {
this.glueRemark = glueRemark;
}
public String getChildJobKey() {
return childJobKey;
}
public void setChildJobKey(String childJobKey) {
this.childJobKey = childJobKey;
}
public String getJobStatus() {
return jobStatus;
}

@ -14,10 +14,11 @@ public interface IXxlJobService {
public Map<String, Object> pageList(int start, int length, String jobGroup, String executorHandler, String filterTime);
public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc,String author, String alarmEmail,
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark);
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark,
String childJobKey);
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
String executorAddress, String executorHandler, String executorParam, int glueSwitch);
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String childJobKey);
public ReturnT<String> remove(String jobGroup, String jobName);

@ -61,7 +61,8 @@ public class XxlJobServiceImpl implements IXxlJobService {
@Override
public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc, String author, String alarmEmail,
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark) {
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark,
String childJobKey) {
// valid
if (JobGroupEnum.match(jobGroup) == null) {
return new ReturnT<String>(500, "请选择“任务组”");
@ -110,6 +111,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
jobInfo.setGlueSwitch(glueSwitch);
jobInfo.setGlueSource(glueSource);
jobInfo.setGlueRemark(glueRemark);
jobInfo.setChildJobKey(childJobKey);
try {
// add job 2 quartz
@ -128,7 +130,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
@Override
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
String executorAddress, String executorHandler, String executorParam, int glueSwitch) {
String executorAddress, String executorHandler, String executorParam, int glueSwitch, String childJobKey) {
// valid
if (JobGroupEnum.match(jobGroup) == null) {
@ -166,6 +168,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
jobInfo.setExecutorHandler(executorHandler);
jobInfo.setExecutorParam(executorParam);
jobInfo.setGlueSwitch(glueSwitch);
jobInfo.setChildJobKey(childJobKey);
try {
// fresh quartz

@ -24,6 +24,8 @@
<result column="glue_switch" property="glueSwitch" />
<result column="glue_source" property="glueSource" />
<result column="glue_remark" property="glueRemark" />
<result column="child_jobkey" property="childJobKey" />
</resultMap>
<sql id="Base_Column_List">
@ -41,7 +43,8 @@
t.executor_param,
t.glue_switch,
t.glue_source,
t.glue_remark
t.glue_remark,
t.child_jobkey
</sql>
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
@ -87,7 +90,8 @@
executor_param,
glue_switch,
glue_source,
glue_remark
glue_remark,
child_jobkey
) VALUES (
#{jobGroup},
#{jobName},
@ -102,7 +106,8 @@
#{executorParam},
#{glueSwitch},
#{glueSource},
#{glueRemark}
#{glueRemark},
#{childJobKey}
);
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
@ -129,7 +134,8 @@
executor_param = #{executorParam},
glue_switch = #{glueSwitch},
glue_source = #{glueSource},
glue_remark = #{glueRemark}
glue_remark = #{glueRemark},
child_jobkey = #{childJobKey}
WHERE job_group = #{jobGroup}
AND job_name = #{jobName}
</update>

@ -168,7 +168,7 @@
<#macro commonFooter >
<footer class="main-footer">
<div class="pull-right hidden-xs">
<b>Version</b> 1.3
<b>Version</b> 1.4
</div>
<strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp;
<a href="https://github.com/xuxueli/xxl-job" target="_blank" >github</a>&nbsp;

@ -75,6 +75,7 @@
<th name="id" >id</th>
<th name="jobGroup" >jobGroup</th>
<th name="jobName" >jobName</th>
<th name="childJobKey" >任务Key</th>
<th name="jobDesc" >描述</th>
<th name="jobCron" >Cron</th>
<th name="executorAddress" >执行器地址</th>
@ -148,6 +149,10 @@
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key" maxlength="100" ></div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
@ -219,13 +224,16 @@ public class DemoJobHandler extends IJobHandler {
<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key" maxlength="100" ></div>
</div>
<hr>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">

@ -35,6 +35,14 @@ $(function() {
}
},
{ "data": 'jobName', "visible" : false},
{
"data": 'childJobKey',
"visible" : true,
"render": function ( data, type, row ) {
var jobKey = row.jobGroup + "_" + row.jobName;
return jobKey;
}
},
{ "data": 'jobDesc', "visible" : true},
{ "data": 'jobCron', "visible" : true},
{ "data": 'executorAddress', "visible" : false},
@ -103,6 +111,7 @@ $(function() {
' executorHandler="'+row.executorHandler +'" '+
' executorParam="'+ row.executorParam +'" '+
' glueSwitch="'+ row.glueSwitch +'" '+
' childJobKey="'+ row.childJobKey +'" '+
'>'+
'<button class="btn btn-primary btn-xs job_operate" type="job_trigger" type="button">执行</button> '+
pause_resume +
@ -284,6 +293,8 @@ $(function() {
addModalValidate.resetForm();
$("#addModal .form .form-group").removeClass("has-error");
$(".remote_panel").show(); // remote
$("#addModal .form input[name='executorHandler']").removeAttr("readonly");
});
// GLUE模式开启
@ -314,6 +325,7 @@ $(function() {
$("#updateModal .form input[name='executorAddress']").val($(this).parent('p').attr("executorAddress"));
$("#updateModal .form input[name='executorHandler']").val($(this).parent('p').attr("executorHandler"));
$("#updateModal .form input[name='executorParam']").val($(this).parent('p').attr("executorParam"));
$("#updateModal .form input[name='childJobKey']").val($(this).parent('p').attr("childJobKey"));
// jobGroupTitle
var jobGroupTitle = $("#addModal .form select[name='jobGroup']").find("option[value='" + $(this).parent('p').attr("jobGroup") + "']").text();

Loading…
Cancel
Save