Browse Source

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

xueli.xue 8 years ago
parent
commit
8048b0c78c

+ 1 - 0
db/tables_xxl_job.sql

@@ -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;
 

+ 5 - 4
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobInfoController.java

@@ -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")

+ 33 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/callback/XxlJobLogCallbackServerHandler.java

@@ -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());

+ 10 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java

@@ -28,6 +28,8 @@ public class XxlJobInfo {
 	private int glueSwitch;		// GLUE模式开关:0-否,1-是
 	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;
 	}

+ 3 - 2
xxl-job-admin/src/main/java/com/xxl/job/admin/service/IXxlJobService.java

@@ -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);
 	

+ 5 - 2
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java

@@ -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

+ 10 - 4
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml

@@ -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>

+ 1 - 1
xxl-job-admin/src/main/webapp/WEB-INF/template/common/common.macro.ftl

@@ -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;

+ 9 - 1
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl

@@ -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">

+ 12 - 0
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js

@@ -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();