Преглед изворни кода

失败重试完整支持:任务流程分为调度和执行,之前仅支持调度失败的重试;目前支持执行失败的重试,通过任务返回值判断。

xuxueli пре 8 година
родитељ
комит
f587f10e32
14 измењених фајлова са 69 додато и 27 уклоњено
  1. 2 1
      doc/XXL-JOB官方文档.md
  2. 6 3
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java
  3. 1 1
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/XxlJobTrigger.java
  4. 22 10
      xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/AdminBizImpl.java
  5. 20 3
      xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js
  6. 10 1
      xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java
  7. 1 1
      xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java
  8. 1 1
      xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java
  9. 1 1
      xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/DemoJobHandler.java
  10. 1 1
      xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/ShardingJobHandler.java
  11. 1 1
      xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java
  12. 1 1
      xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java
  13. 1 1
      xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java
  14. 1 1
      xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java

+ 2 - 1
doc/XXL-JOB官方文档.md Прегледај датотеку

1065
 - 11、任务Cron长度扩展支持至128位;
1065
 - 11、任务Cron长度扩展支持至128位;
1066
 - 12、调度报表优化,支持时间区间筛选;
1066
 - 12、调度报表优化,支持时间区间筛选;
1067
 - 13、Log组件支持输出异常栈信息,底层实现优化;
1067
 - 13、Log组件支持输出异常栈信息,底层实现优化;
1068
+- 14、失败重试完整支持:任务流程分为调度和执行,之前仅支持调度失败的重试;目前支持执行失败的重试,通过任务返回值判断。
1068
 
1069
 
1069
 ### TODO LIST
1070
 ### TODO LIST
1070
 - 1、任务权限管理:执行器为粒度分配权限,核心操作校验权限;
1071
 - 1、任务权限管理:执行器为粒度分配权限,核心操作校验权限;
1085
 - 16、任务告警邮件优化,调整为表格形式;
1086
 - 16、任务告警邮件优化,调整为表格形式;
1086
 - 17、JobHandler提供 init/destroy 方法,支持自定义任务线程销毁逻辑;
1087
 - 17、JobHandler提供 init/destroy 方法,支持自定义任务线程销毁逻辑;
1087
 - 18、执行器回调地址/日志地址格式兼容,是否已"/"结尾均支持;
1088
 - 18、执行器回调地址/日志地址格式兼容,是否已"/"结尾均支持;
1088
-- 19、失败重试完整支持:任务流程分为触发和执行,目前仅支持触发失败的重试;后续支持任务执行失败的重试,通过任务返回值判断。
1089
+
1089
 
1090
 
1090
 
1091
 
1091
 
1092
 

+ 6 - 3
xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java Прегледај датотеку

6
 import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
6
 import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
7
 import com.xxl.job.admin.core.util.MailUtil;
7
 import com.xxl.job.admin.core.util.MailUtil;
8
 import com.xxl.job.core.biz.model.ReturnT;
8
 import com.xxl.job.core.biz.model.ReturnT;
9
+import com.xxl.job.core.handler.IJobHandler;
9
 import org.apache.commons.collections.CollectionUtils;
10
 import org.apache.commons.collections.CollectionUtils;
10
 import org.slf4j.Logger;
11
 import org.slf4j.Logger;
11
 import org.slf4j.LoggerFactory;
12
 import org.slf4j.LoggerFactory;
51
 								if (log == null) {
52
 								if (log == null) {
52
 									continue;
53
 									continue;
53
 								}
54
 								}
54
-								if (ReturnT.SUCCESS_CODE == log.getTriggerCode() && log.getHandleCode() == 0) {
55
+								if (IJobHandler.SUCCESS.getCode() == log.getTriggerCode() && log.getHandleCode() == 0) {
55
 									JobFailMonitorHelper.monitor(jobLogId);
56
 									JobFailMonitorHelper.monitor(jobLogId);
56
 									logger.info(">>>>>>>>>>> job monitor, job running, JobLogId:{}", jobLogId);
57
 									logger.info(">>>>>>>>>>> job monitor, job running, JobLogId:{}", jobLogId);
57
-								} else if (ReturnT.SUCCESS_CODE == log.getTriggerCode() && ReturnT.SUCCESS_CODE == log.getHandleCode()) {
58
+								} else if (IJobHandler.SUCCESS.getCode() == log.getHandleCode()) {
58
 									// job success, pass
59
 									// job success, pass
59
 									logger.info(">>>>>>>>>>> job monitor, job success, JobLogId:{}", jobLogId);
60
 									logger.info(">>>>>>>>>>> job monitor, job success, JobLogId:{}", jobLogId);
60
-								} else if (ReturnT.FAIL_CODE == log.getTriggerCode() || ReturnT.FAIL_CODE == log.getHandleCode()) {
61
+								} else if (IJobHandler.FAIL.getCode() == log.getTriggerCode()
62
+										|| IJobHandler.FAIL.getCode() == log.getHandleCode()
63
+										|| IJobHandler.FAIL_RETRY.getCode() == log.getHandleCode() ) {
61
 									// job fail,
64
 									// job fail,
62
 									failAlarm(log);
65
 									failAlarm(log);
63
 									logger.info(">>>>>>>>>>> job monitor, job fail, JobLogId:{}", jobLogId);
66
 									logger.info(">>>>>>>>>>> job monitor, job fail, JobLogId:{}", jobLogId);

+ 1 - 1
xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/XxlJobTrigger.java Прегледај датотеку

171
             // 4.3、trigger (fail retry)
171
             // 4.3、trigger (fail retry)
172
             if (triggerResult.getCode()!=ReturnT.SUCCESS_CODE && failStrategy == ExecutorFailStrategyEnum.FAIL_RETRY) {
172
             if (triggerResult.getCode()!=ReturnT.SUCCESS_CODE && failStrategy == ExecutorFailStrategyEnum.FAIL_RETRY) {
173
                 triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);
173
                 triggerResult = executorRouteStrategyEnum.getRouter().routeRun(triggerParam, addressList);
174
-                triggerMsgSb.append("<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>失败重试<<<<<<<<<<< </span><br>").append(triggerResult.getMsg());
174
+                triggerMsgSb.append("<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>调度失败重试<<<<<<<<<<< </span><br>").append(triggerResult.getMsg());
175
             }
175
             }
176
         }
176
         }
177
 
177
 

+ 22 - 10
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/AdminBizImpl.java Прегледај датотеку

13
 import com.xxl.job.core.biz.model.HandleCallbackParam;
13
 import com.xxl.job.core.biz.model.HandleCallbackParam;
14
 import com.xxl.job.core.biz.model.RegistryParam;
14
 import com.xxl.job.core.biz.model.RegistryParam;
15
 import com.xxl.job.core.biz.model.ReturnT;
15
 import com.xxl.job.core.biz.model.ReturnT;
16
+import com.xxl.job.core.handler.IJobHandler;
16
 import org.apache.commons.lang.StringUtils;
17
 import org.apache.commons.lang.StringUtils;
17
 import org.quartz.SchedulerException;
18
 import org.quartz.SchedulerException;
18
 import org.slf4j.Logger;
19
 import org.slf4j.Logger;
46
         for (HandleCallbackParam handleCallbackParam: callbackParamList) {
47
         for (HandleCallbackParam handleCallbackParam: callbackParamList) {
47
             ReturnT<String> callbackResult = callback(handleCallbackParam);
48
             ReturnT<String> callbackResult = callback(handleCallbackParam);
48
             logger.info(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
49
             logger.info(">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}",
49
-                    (callbackResult.getCode()==ReturnT.SUCCESS_CODE?"success":"fail"), handleCallbackParam, callbackResult);
50
+                    (callbackResult.getCode()==IJobHandler.SUCCESS.getCode()?"success":"fail"), handleCallbackParam, callbackResult);
50
         }
51
         }
51
 
52
 
52
         return ReturnT.SUCCESS;
53
         return ReturnT.SUCCESS;
58
         if (log == null) {
59
         if (log == null) {
59
             return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
60
             return new ReturnT<String>(ReturnT.FAIL_CODE, "log item not found.");
60
         }
61
         }
62
+        if (log.getHandleCode() > 0) {
63
+            return new ReturnT<String>(ReturnT.FAIL_CODE, "log repeate callback.");     // avoid repeat callback, trigger child job etc
64
+        }
61
 
65
 
62
-        // trigger success, to trigger child job, and avoid repeat trigger child job
63
-        String childTriggerMsg = null;
64
-        if (ReturnT.SUCCESS_CODE==handleCallbackParam.getExecuteResult().getCode() && ReturnT.SUCCESS_CODE!=log.getHandleCode()) {
66
+        // trigger success, to trigger child job
67
+        String callbackMsg = null;
68
+        if (IJobHandler.SUCCESS.getCode() == handleCallbackParam.getExecuteResult().getCode()) {
65
             XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(log.getJobId());
69
             XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(log.getJobId());
66
             if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) {
70
             if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) {
67
-                childTriggerMsg = "<hr>";
71
+                callbackMsg = "<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发子任务<<<<<<<<<<< </span><br>";
72
+
68
                 String[] childJobKeys = xxlJobInfo.getChildJobKey().split(",");
73
                 String[] childJobKeys = xxlJobInfo.getChildJobKey().split(",");
69
                 for (int i = 0; i < childJobKeys.length; i++) {
74
                 for (int i = 0; i < childJobKeys.length; i++) {
70
                     String[] jobKeyArr = childJobKeys[i].split("_");
75
                     String[] jobKeyArr = childJobKeys[i].split("_");
71
                     if (jobKeyArr!=null && jobKeyArr.length==2) {
76
                     if (jobKeyArr!=null && jobKeyArr.length==2) {
72
                         ReturnT<String> triggerChildResult = xxlJobService.triggerJob(Integer.valueOf(jobKeyArr[1]));
77
                         ReturnT<String> triggerChildResult = xxlJobService.triggerJob(Integer.valueOf(jobKeyArr[1]));
78
+
73
                         // add msg
79
                         // add msg
74
-                        childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务{2}, 子任务Key: {3}, 子任务触发备注: {4}",
75
-                                (i+1), childJobKeys.length, (triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?"成功":"失败"), childJobKeys[i], triggerChildResult.getMsg());
80
+                        callbackMsg += MessageFormat.format("{0}/{1} [JobKey={2}], 触发{3}, 触发备注: {4} <br>",
81
+                                (i+1), childJobKeys.length, childJobKeys[i], (triggerChildResult.getCode()==ReturnT.SUCCESS_CODE?"成功":"失败"), triggerChildResult.getMsg());
76
                     } else {
82
                     } else {
77
-                        childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务失败, 子任务Key格式错误, 子任务Key: {2}",
83
+                        callbackMsg += MessageFormat.format(" {0}/{1} [JobKey={2}], 触发失败, 触发备注: JobKey格式错误 <br>",
78
                                 (i+1), childJobKeys.length, childJobKeys[i]);
84
                                 (i+1), childJobKeys.length, childJobKeys[i]);
79
                     }
85
                     }
80
                 }
86
                 }
81
 
87
 
82
             }
88
             }
89
+        } else if (IJobHandler.FAIL_RETRY.getCode() == handleCallbackParam.getExecuteResult().getCode()){
90
+            ReturnT<String> retryTriggerResult = xxlJobService.triggerJob(log.getJobId());
91
+            callbackMsg = "<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>执行失败重试<<<<<<<<<<< </span><br>";
92
+
93
+            callbackMsg += MessageFormat.format("触发{0}, 触发备注: {1}",
94
+                   (retryTriggerResult.getCode()==ReturnT.SUCCESS_CODE?"成功":"失败"), retryTriggerResult.getMsg());
83
         }
95
         }
84
 
96
 
85
         // handle msg
97
         // handle msg
90
         if (handleCallbackParam.getExecuteResult().getMsg() != null) {
102
         if (handleCallbackParam.getExecuteResult().getMsg() != null) {
91
             handleMsg.append(handleCallbackParam.getExecuteResult().getMsg());
103
             handleMsg.append(handleCallbackParam.getExecuteResult().getMsg());
92
         }
104
         }
93
-        if (childTriggerMsg !=null) {
94
-            handleMsg.append("<br>子任务触发备注:").append(childTriggerMsg);
105
+        if (callbackMsg != null) {
106
+            handleMsg.append(callbackMsg);
95
         }
107
         }
96
 
108
 
97
         // success, save log
109
         // success, save log

+ 20 - 3
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js Прегледај датотеку

146
 					{
146
 					{
147
 						"data": 'triggerCode',
147
 						"data": 'triggerCode',
148
 						"render": function ( data, type, row ) {
148
 						"render": function ( data, type, row ) {
149
-							return (data==200)?'<span style="color: green">成功</span>':(data==500)?'<span style="color: red">失败</span>':(data==0)?'':data;
149
+							var html = data;
150
+							if (data == 200) {
151
+								html = '<span style="color: green">成功</span>';
152
+							} else if (data == 500) {
153
+								html = '<span style="color: red">失败</span>';
154
+							} else if (data == 0) {
155
+                                html = '';
156
+							}
157
+                            return html;
150
 						}
158
 						}
151
-
152
 					},
159
 					},
153
 					{
160
 					{
154
 						"data": 'triggerMsg',
161
 						"data": 'triggerMsg',
165
 	                {
172
 	                {
166
 						"data": 'handleCode',
173
 						"data": 'handleCode',
167
 						"render": function ( data, type, row ) {
174
 						"render": function ( data, type, row ) {
168
-							return (data==200)?'<span style="color: green">成功</span>':(data==500)?'<span style="color: red">失败</span>':(data==0)?'':data;
175
+                            var html = data;
176
+                            if (data == 200) {
177
+                                html = '<span style="color: green">成功</span>';
178
+                            } else if (data == 500) {
179
+                                html = '<span style="color: red">失败</span>';
180
+                            } else if (data == 501) {
181
+                                html = '<span style="color: red">失败重试</span>';
182
+                            } else if (data == 0) {
183
+                                html = '';
184
+                            }
185
+                            return html;
169
 						}
186
 						}
170
 	                },
187
 	                },
171
 	                { 
188
 	                { 

+ 10 - 1
xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java Прегледај датотеку

3
 import com.xxl.job.core.biz.model.ReturnT;
3
 import com.xxl.job.core.biz.model.ReturnT;
4
 
4
 
5
 /**
5
 /**
6
- * remote job handler
6
+ * job handler
7
+ *
7
  * @author xuxueli 2015-12-19 19:06:38
8
  * @author xuxueli 2015-12-19 19:06:38
8
  */
9
  */
9
 public abstract class IJobHandler {
10
 public abstract class IJobHandler {
10
 
11
 
12
+	/** success */
13
+	public static final ReturnT<String> SUCCESS = new ReturnT<String>(200, null);
14
+	/** fail */
15
+	public static final ReturnT<String> FAIL = new ReturnT<String>(500, null);
16
+	/** fail retry */
17
+	public static final ReturnT<String> FAIL_RETRY = new ReturnT<String>(501, null);
18
+
19
+
11
 	/**
20
 	/**
12
 	 * job handler
21
 	 * job handler
13
 	 * @param params
22
 	 * @param params

+ 1 - 1
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java Прегледај датотеку

54
         // invoke
54
         // invoke
55
         XxlJobLogger.log("----------- script file:"+ scriptFileName +" -----------");
55
         XxlJobLogger.log("----------- script file:"+ scriptFileName +" -----------");
56
         int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, params);
56
         int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, params);
57
-        ReturnT<String> result = (exitValue==0)?ReturnT.SUCCESS:new ReturnT<String>(ReturnT.FAIL_CODE, "script exit value("+exitValue+") is failed");
57
+        ReturnT<String> result = (exitValue==0)?IJobHandler.SUCCESS:new ReturnT<String>(IJobHandler.FAIL.getCode(), "script exit value("+exitValue+") is failed");
58
         return result;
58
         return result;
59
     }
59
     }
60
 
60
 

+ 1 - 1
xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java Прегледај датотеку

120
 					XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Params:" + Arrays.toString(handlerParams));
120
 					XxlJobLogger.log("<br>----------- xxl-job job execute start -----------<br>----------- Params:" + Arrays.toString(handlerParams));
121
 					executeResult = handler.execute(handlerParams);
121
 					executeResult = handler.execute(handlerParams);
122
 					if (executeResult == null) {
122
 					if (executeResult == null) {
123
-						executeResult = ReturnT.FAIL;
123
+						executeResult = IJobHandler.FAIL;
124
 					}
124
 					}
125
 					XxlJobLogger.log("<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:" + executeResult);
125
 					XxlJobLogger.log("<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:" + executeResult);
126
 
126
 

+ 1 - 1
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/DemoJobHandler.java Прегледај датотеку

27
 			XxlJobLogger.log("beat at:" + i);
27
 			XxlJobLogger.log("beat at:" + i);
28
 			TimeUnit.SECONDS.sleep(2);
28
 			TimeUnit.SECONDS.sleep(2);
29
 		}
29
 		}
30
-		return ReturnT.SUCCESS;
30
+		return SUCCESS;
31
 	}
31
 	}
32
 
32
 
33
 }
33
 }

+ 1 - 1
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/ShardingJobHandler.java Прегледај датотеку

29
 			}
29
 			}
30
 		}
30
 		}
31
 
31
 
32
-		return ReturnT.SUCCESS;
32
+		return SUCCESS;
33
 	}
33
 	}
34
 	
34
 	
35
 }
35
 }

+ 1 - 1
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java Прегледај датотеку

32
 			XxlJobLogger.log("beat at:" + i);
32
 			XxlJobLogger.log("beat at:" + i);
33
 			TimeUnit.SECONDS.sleep(2);
33
 			TimeUnit.SECONDS.sleep(2);
34
 		}
34
 		}
35
-		return ReturnT.SUCCESS;
35
+		return SUCCESS;
36
 	}
36
 	}
37
 	
37
 	
38
 }
38
 }

+ 1 - 1
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java Прегледај датотеку

33
 			}
33
 			}
34
 		}
34
 		}
35
 
35
 
36
-		return ReturnT.SUCCESS;
36
+		return SUCCESS;
37
 	}
37
 	}
38
 	
38
 	
39
 }
39
 }

+ 1 - 1
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java Прегледај датотеку

32
 			XxlJobLogger.log("beat at:" + i);
32
 			XxlJobLogger.log("beat at:" + i);
33
 			TimeUnit.SECONDS.sleep(2);
33
 			TimeUnit.SECONDS.sleep(2);
34
 		}
34
 		}
35
-		return ReturnT.SUCCESS;
35
+		return SUCCESS;
36
 	}
36
 	}
37
 
37
 
38
 }
38
 }

+ 1 - 1
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java Прегледај датотеку

33
 			}
33
 			}
34
 		}
34
 		}
35
 
35
 
36
-		return ReturnT.SUCCESS;
36
+		return SUCCESS;
37
 	}
37
 	}
38
 
38
 
39
 }
39
 }