Browse Source

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

xueli.xue 9 years ago
parent
commit
8048b0c78c

+ 1 - 0
db/tables_xxl_job.sql View File

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

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

@@ -41,19 +41,20 @@ public class JobInfoController {
41 41
 	@RequestMapping("/add")
42 42
 	@ResponseBody
43 43
 	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc, String author, String alarmEmail,
44
-			String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark) {
44
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark,
45
+			String childJobKey) {
45 46
 		
46 47
 		return xxlJobService.add(jobGroup, jobCron, jobDesc, author, alarmEmail,
47
-				executorAddress, executorHandler, executorParam, glueSwitch, glueSource, glueRemark);
48
+				executorAddress, executorHandler, executorParam, glueSwitch, glueSource, glueRemark, childJobKey);
48 49
 	}
49 50
 	
50 51
 	@RequestMapping("/reschedule")
51 52
 	@ResponseBody
52 53
 	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
53
-			String executorAddress, String executorHandler, String executorParam, int glueSwitch) {
54
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch, String childJobKey) {
54 55
 
55 56
 		return xxlJobService.reschedule(jobGroup, jobName, jobCron, jobDesc, author, alarmEmail,
56
-				executorAddress, executorHandler, executorParam, glueSwitch);
57
+				executorAddress, executorHandler, executorParam, glueSwitch, childJobKey);
57 58
 	}
58 59
 	
59 60
 	@RequestMapping("/remove")

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

@@ -1,23 +1,31 @@
1 1
 package com.xxl.job.admin.core.callback;
2 2
 
3
+import com.xxl.job.admin.core.model.ReturnT;
4
+import com.xxl.job.admin.core.model.XxlJobInfo;
3 5
 import com.xxl.job.admin.core.model.XxlJobLog;
4 6
 import com.xxl.job.admin.core.util.DynamicSchedulerUtil;
5 7
 import com.xxl.job.core.router.model.RequestModel;
6 8
 import com.xxl.job.core.router.model.ResponseModel;
7 9
 import com.xxl.job.core.util.XxlJobNetCommUtil;
10
+import org.apache.commons.lang.StringUtils;
8 11
 import org.eclipse.jetty.server.Request;
9 12
 import org.eclipse.jetty.server.handler.AbstractHandler;
13
+import org.quartz.SchedulerException;
14
+import org.slf4j.Logger;
15
+import org.slf4j.LoggerFactory;
10 16
 
11 17
 import javax.servlet.ServletException;
12 18
 import javax.servlet.http.HttpServletRequest;
13 19
 import javax.servlet.http.HttpServletResponse;
14 20
 import java.io.IOException;
21
+import java.text.MessageFormat;
15 22
 import java.util.Date;
16 23
 
17 24
 /**
18 25
  * Created by xuxueli on 2016-5-22 11:15:42
19 26
  */
20 27
 public class XxlJobLogCallbackServerHandler extends AbstractHandler {
28
+	private static Logger logger = LoggerFactory.getLogger(XxlJobLogCallbackServerHandler.class);
21 29
 
22 30
 	@Override
23 31
 	public void handle(String s, Request baseRequest, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
@@ -33,6 +41,31 @@ public class XxlJobLogCallbackServerHandler extends AbstractHandler {
33 41
 		ResponseModel responseModel = null;
34 42
 		XxlJobLog log = DynamicSchedulerUtil.xxlJobLogDao.load(requestModel.getLogId());
35 43
 		if (log!=null) {
44
+
45
+			// trigger success, to trigger child job, and avoid repeat trigger child job
46
+			if (!ResponseModel.SUCCESS.equals(log.getHandleStatus())) {
47
+				XxlJobInfo xxlJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
48
+				if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) {
49
+					String[] jobKeyArr = xxlJobInfo.getChildJobKey().split("_");
50
+					if (jobKeyArr!=null && jobKeyArr.length==2) {
51
+						XxlJobInfo childJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKeyArr[0], jobKeyArr[1]);
52
+						if (childJobInfo!=null) {
53
+							try {
54
+								boolean ret = DynamicSchedulerUtil.triggerJob(childJobInfo.getJobName(), childJobInfo.getJobGroup());
55
+
56
+								// add msg
57
+								String msg = requestModel.getMsg();
58
+								msg += MessageFormat.format("<br> 触发子任务执行, jobKey:{0}, status:{1}, 描述:{2}", xxlJobInfo.getChildJobKey(), ret, childJobInfo.getJobDesc());
59
+								requestModel.setMsg(msg);
60
+							} catch (SchedulerException e) {
61
+								logger.error("", e);
62
+							}
63
+						}
64
+					}
65
+				}
66
+			}
67
+
68
+			// save log
36 69
 			log.setHandleTime(new Date());
37 70
 			log.setHandleStatus(requestModel.getStatus());
38 71
 			log.setHandleMsg(requestModel.getMsg());

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

@@ -28,6 +28,8 @@ public class XxlJobInfo {
28 28
 	private int glueSwitch;		// GLUE模式开关:0-否,1-是
29 29
 	private String glueSource;	// GLUE源代码
30 30
 	private String glueRemark;	// GLUE备注
31
+
32
+	private String childJobKey;		// 子任务Key
31 33
 	
32 34
 	// copy from quartz
33 35
 	private String jobStatus;	// 任务状态 【base on quartz】
@@ -152,6 +154,14 @@ public class XxlJobInfo {
152 154
 		this.glueRemark = glueRemark;
153 155
 	}
154 156
 
157
+	public String getChildJobKey() {
158
+		return childJobKey;
159
+	}
160
+
161
+	public void setChildJobKey(String childJobKey) {
162
+		this.childJobKey = childJobKey;
163
+	}
164
+
155 165
 	public String getJobStatus() {
156 166
 		return jobStatus;
157 167
 	}

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

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

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

@@ -61,7 +61,8 @@ public class XxlJobServiceImpl implements IXxlJobService {
61 61
 
62 62
 	@Override
63 63
 	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc, String author, String alarmEmail,
64
-			String executorAddress,	String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark) {
64
+			String executorAddress,	String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark,
65
+			String childJobKey) {
65 66
 		// valid
66 67
 		if (JobGroupEnum.match(jobGroup) == null) {
67 68
 			return new ReturnT<String>(500, "请选择“任务组”");
@@ -110,6 +111,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
110 111
 		jobInfo.setGlueSwitch(glueSwitch);
111 112
 		jobInfo.setGlueSource(glueSource);
112 113
 		jobInfo.setGlueRemark(glueRemark);
114
+		jobInfo.setChildJobKey(childJobKey);
113 115
 
114 116
 		try {
115 117
 			// add job 2 quartz
@@ -128,7 +130,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
128 130
 
129 131
 	@Override
130 132
 	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
131
-			String executorAddress, String executorHandler, String executorParam, int glueSwitch) {
133
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch, String childJobKey) {
132 134
 
133 135
 		// valid
134 136
 		if (JobGroupEnum.match(jobGroup) == null) {
@@ -166,6 +168,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
166 168
 		jobInfo.setExecutorHandler(executorHandler);
167 169
 		jobInfo.setExecutorParam(executorParam);
168 170
 		jobInfo.setGlueSwitch(glueSwitch);
171
+		jobInfo.setChildJobKey(childJobKey);
169 172
 		
170 173
 		try {
171 174
 			// fresh quartz

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

@@ -24,6 +24,8 @@
24 24
 	    <result column="glue_switch" property="glueSwitch" />
25 25
 	    <result column="glue_source" property="glueSource" />
26 26
 	    <result column="glue_remark" property="glueRemark" />
27
+
28
+		<result column="child_jobkey" property="childJobKey" />
27 29
 	</resultMap>
28 30
 
29 31
 	<sql id="Base_Column_List">
@@ -41,7 +43,8 @@
41 43
 		t.executor_param,
42 44
 		t.glue_switch,
43 45
 		t.glue_source,
44
-		t.glue_remark
46
+		t.glue_remark,
47
+		t.child_jobkey
45 48
 	</sql>
46 49
 	
47 50
 	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
@@ -87,7 +90,8 @@
87 90
 			executor_param,
88 91
 			glue_switch,
89 92
 			glue_source,
90
-			glue_remark
93
+			glue_remark,
94
+			child_jobkey
91 95
 		) VALUES (
92 96
 			#{jobGroup}, 
93 97
 			#{jobName}, 
@@ -102,7 +106,8 @@
102 106
 			#{executorParam},
103 107
 			#{glueSwitch},
104 108
 			#{glueSource},
105
-			#{glueRemark}
109
+			#{glueRemark},
110
+			#{childJobKey}
106 111
 		);
107 112
 		<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> 
108 113
 			SELECT LAST_INSERT_ID() 
@@ -129,7 +134,8 @@
129 134
 			executor_param = #{executorParam},
130 135
 			glue_switch = #{glueSwitch},
131 136
 			glue_source = #{glueSource},
132
-			glue_remark = #{glueRemark}
137
+			glue_remark = #{glueRemark},
138
+			child_jobkey = #{childJobKey}
133 139
 		WHERE job_group = #{jobGroup}
134 140
 			AND job_name = #{jobName}
135 141
 	</update>

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

@@ -168,7 +168,7 @@
168 168
 <#macro commonFooter >
169 169
 	<footer class="main-footer">
170 170
 		<div class="pull-right hidden-xs">
171
-			<b>Version</b> 1.3
171
+			<b>Version</b> 1.4
172 172
 		</div>
173 173
 		<strong>Copyright &copy; 2015-${.now?string('yyyy')} &nbsp;
174 174
 			<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 View File

@@ -75,6 +75,7 @@
75 75
 					            		<th name="id" >id</th>
76 76
 					                	<th name="jobGroup" >jobGroup</th>
77 77
 					                  	<th name="jobName" >jobName</th>
78
+                                        <th name="childJobKey" >任务Key</th>
78 79
 					                  	<th name="jobDesc" >描述</th>
79 80
 					                  	<th name="jobCron" >Cron</th>
80 81
 					                  	<th name="executorAddress" >执行器地址</th>
@@ -148,6 +149,10 @@
148 149
                         <label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
149 150
                         <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
150 151
 					</div>
152
+                    <div class="form-group">
153
+                        <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
154
+                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key" maxlength="100" ></div>
155
+                    </div>
151 156
                     <hr>
152 157
 					<div class="form-group">
153 158
 						<div class="col-sm-offset-3 col-sm-6">
@@ -219,13 +224,16 @@ public class DemoJobHandler extends IJobHandler {
219 224
                         <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
220 225
                         <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
221 226
                     </div>
222
-
223 227
 					<div class="form-group">
224 228
 						<label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
225 229
 						<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="100" ></div>
226 230
                         <label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
227 231
                         <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
228 232
 					</div>
233
+                    <div class="form-group">
234
+                        <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
235
+                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key" maxlength="100" ></div>
236
+                    </div>
229 237
 					<hr>
230 238
 					<div class="form-group">
231 239
                         <div class="col-sm-offset-3 col-sm-6">

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

@@ -35,6 +35,14 @@ $(function() {
35 35
 	            		}
36 36
             		},
37 37
 					{ "data": 'jobName', "visible" : false},
38
+					{
39
+						"data": 'childJobKey',
40
+						"visible" : true,
41
+						"render": function ( data, type, row ) {
42
+							var jobKey = row.jobGroup + "_" + row.jobName;
43
+							return jobKey;
44
+						}
45
+					},
38 46
 	                { "data": 'jobDesc', "visible" : true},
39 47
 	                { "data": 'jobCron', "visible" : true},
40 48
 	                { "data": 'executorAddress', "visible" : false},
@@ -103,6 +111,7 @@ $(function() {
103 111
 									' executorHandler="'+row.executorHandler +'" '+
104 112
 									' executorParam="'+ row.executorParam +'" '+
105 113
 									' glueSwitch="'+ row.glueSwitch +'" '+
114
+                                    ' childJobKey="'+ row.childJobKey +'" '+
106 115
 									'>'+
107 116
 									'<button class="btn btn-primary btn-xs job_operate" type="job_trigger" type="button">执行</button>  '+
108 117
 									pause_resume +
@@ -284,6 +293,8 @@ $(function() {
284 293
 		addModalValidate.resetForm();
285 294
 		$("#addModal .form .form-group").removeClass("has-error");
286 295
 		$(".remote_panel").show();	// remote
296
+
297
+		$("#addModal .form input[name='executorHandler']").removeAttr("readonly");
287 298
 	});
288 299
 
289 300
 	// GLUE模式开启
@@ -314,6 +325,7 @@ $(function() {
314 325
 		$("#updateModal .form input[name='executorAddress']").val($(this).parent('p').attr("executorAddress"));
315 326
 		$("#updateModal .form input[name='executorHandler']").val($(this).parent('p').attr("executorHandler"));
316 327
 		$("#updateModal .form input[name='executorParam']").val($(this).parent('p').attr("executorParam"));
328
+        $("#updateModal .form input[name='childJobKey']").val($(this).parent('p').attr("childJobKey"));
317 329
 
318 330
 		// jobGroupTitle
319 331
 		var jobGroupTitle = $("#addModal .form select[name='jobGroup']").find("option[value='" + $(this).parent('p').attr("jobGroup") + "']").text();