refactor(core): xxl-job-admin 3.0

This commit is contained in:
冷冷 committed 2025-02-17 17:29:12 +08:00
1 parent cb131319be
commit 803cf33d1e
32 files changed
+313 -224

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@
<description>xxl job admin 控制台内置方便开发</description>
<packaging>jar</packaging>
<properties>
<mybatis-spring-boot-starter.version>3.0.3</mybatis-spring-boot-starter.version>
<mybatis-spring-boot-starter.version>3.0.4</mybatis-spring-boot-starter.version>
</properties>
@@ -1,8 +1,8 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.admin.service.impl.LoginService;
import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
@@ -11,10 +11,7 @@ import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
@@ -47,7 +44,8 @@ public class IndexController {
@RequestMapping("/chartInfo")
@ResponseBody
public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
public ReturnT<Map<String, Object>> chartInfo(@RequestParam("startDate") Date startDate,
@RequestParam("endDate") Date endDate) {
ReturnT<Map<String, Object>> chartInfo = xxlJobService.chartInfo(startDate, endDate);
return chartInfo;
}
@@ -65,8 +63,10 @@ public class IndexController {
@RequestMapping(value = "login", method = RequestMethod.POST)
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> loginDo(HttpServletRequest request, HttpServletResponse response, String userName,
String password, String ifRemember) {
public ReturnT<String> loginDo(HttpServletRequest request, HttpServletResponse response,
@RequestParam("userName") String userName, @RequestParam("password") String password,
@RequestParam(value = "ifRemember", required = false) String ifRemember) {
boolean ifRem = (ifRemember != null && ifRemember.trim().length() > 0 && "on".equals(ifRemember)) ? true
: false;
return loginService.login(request, response, userName, password, ifRem);
@@ -13,6 +13,7 @@ import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Date;
@@ -34,7 +35,7 @@ public class JobCodeController {
private XxlJobLogGlueDao xxlJobLogGlueDao;
@RequestMapping
public String index(HttpServletRequest request, Model model, int jobId) {
public String index(HttpServletRequest request, Model model, @RequestParam("jobId") int jobId) {
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
List<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueDao.findByJobId(jobId);
@@ -58,7 +59,9 @@ public class JobCodeController {
@RequestMapping("/save")
@ResponseBody
public ReturnT<String> save(HttpServletRequest request, int id, String glueSource, String glueRemark) {
public ReturnT<String> save(HttpServletRequest request, @RequestParam("id") int id,
@RequestParam("glueSource") String glueSource, @RequestParam("glueRemark") String glueRemark) {
// valid
if (glueRemark == null) {
return new ReturnT<String>(500,
@@ -47,8 +47,9 @@ public class JobGroupController {
@ResponseBody
@PermissionLimit(adminuser = true)
public Map<String, Object> pageList(HttpServletRequest request,
@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length, String appname, String title) {
@RequestParam(value = "start", required = false, defaultValue = "0") int start,
@RequestParam(value = "length", required = false, defaultValue = "10") int length,
@RequestParam("appname") String appname, @RequestParam("title") String title) {
// page query
List<XxlJobGroup> list = xxlJobGroupDao.pageList(start, length, appname, title);
@@ -183,7 +184,7 @@ public class JobGroupController {
@RequestMapping("/remove")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<String> remove(int id) {
public ReturnT<String> remove(@RequestParam("id") int id) {
// valid
int count = xxlJobInfoDao.pageListCount(0, 10, id, -1, null, null, null);
@@ -203,7 +204,7 @@ public class JobGroupController {
@RequestMapping("/loadById")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<XxlJobGroup> loadById(int id) {
public ReturnT<XxlJobGroup> loadById(@RequestParam("id") int id) {
XxlJobGroup jobGroup = xxlJobGroupDao.load(id);
return jobGroup != null ? new ReturnT<XxlJobGroup>(jobGroup)
: new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);
@@ -26,10 +26,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* index controller
@@ -50,7 +47,7 @@ public class JobInfoController {
@RequestMapping
public String index(HttpServletRequest request, Model model,
@RequestParam(required = false, defaultValue = "-1") int jobGroup) {
@RequestParam(value = "jobGroup", required = false, defaultValue = "-1") int jobGroup) {
// 枚举-字典
model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values()); // 路由策略-列表
@@ -76,9 +73,11 @@ public class JobInfoController {
@RequestMapping("/pageList")
@ResponseBody
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length, int jobGroup, int triggerStatus,
String jobDesc, String executorHandler, String author) {
public Map<String, Object> pageList(@RequestParam(value = "start", required = false, defaultValue = "0") int start,
@RequestParam(value = "length", required = false, defaultValue = "10") int length,
@RequestParam("jobGroup") int jobGroup, @RequestParam("triggerStatus") int triggerStatus,
@RequestParam("jobDesc") String jobDesc, @RequestParam("executorHandler") String executorHandler,
@RequestParam("author") String author) {
return xxlJobService.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
}
@@ -107,25 +106,27 @@ public class JobInfoController {
@RequestMapping("/remove")
@ResponseBody
public ReturnT<String> remove(int id) {
public ReturnT<String> remove(@RequestParam("id") int id) {
return xxlJobService.remove(id);
}
@RequestMapping("/stop")
@ResponseBody
public ReturnT<String> pause(int id) {
public ReturnT<String> pause(@RequestParam("id") int id) {
return xxlJobService.stop(id);
}
@RequestMapping("/start")
@ResponseBody
public ReturnT<String> start(int id) {
public ReturnT<String> start(@RequestParam("id") int id) {
return xxlJobService.start(id);
}
@RequestMapping("/trigger")
@ResponseBody
public ReturnT<String> triggerJob(HttpServletRequest request, int id, String executorParam, String addressList) {
public ReturnT<String> triggerJob(HttpServletRequest request, @RequestParam("id") int id,
@RequestParam("executorParam") String executorParam, @RequestParam("addressList") String addressList) {
// login user
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
// trigger
@@ -134,7 +135,8 @@ public class JobInfoController {
@RequestMapping("/nextTriggerTime")
@ResponseBody
public ReturnT<List<String>> nextTriggerTime(String scheduleType, String scheduleConf) {
public ReturnT<List<String>> nextTriggerTime(@RequestParam("scheduleType") String scheduleType,
@RequestParam("scheduleConf") String scheduleConf) {
XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
paramXxlJobInfo.setScheduleType(scheduleType);
@@ -154,7 +156,7 @@ public class JobInfoController {
}
}
catch (Exception e) {
logger.error(e.getMessage(), e);
logger.error("nextTriggerTime error. scheduleType = {}, scheduleConf= {}", scheduleType, scheduleConf, e);
return new ReturnT<List<String>>(ReturnT.FAIL_CODE,
(I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")) + e.getMessage());
}
@@ -56,7 +56,7 @@ public class JobLogController {
@RequestMapping
public String index(HttpServletRequest request, Model model,
@RequestParam(required = false, defaultValue = "0") Integer jobId) {
@RequestParam(value = "jobId", required = false, defaultValue = "0") Integer jobId) {
// 执行器列表
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
@@ -88,7 +88,7 @@ public class JobLogController {
@RequestMapping("/getJobsByGroup")
@ResponseBody
public ReturnT<List<XxlJobInfo>> getJobsByGroup(int jobGroup) {
public ReturnT<List<XxlJobInfo>> getJobsByGroup(@RequestParam("jobGroup") int jobGroup) {
List<XxlJobInfo> list = xxlJobInfoDao.getJobsByGroup(jobGroup);
return new ReturnT<List<XxlJobInfo>>(list);
}
@@ -96,9 +96,10 @@ public class JobLogController {
@RequestMapping("/pageList")
@ResponseBody
public Map<String, Object> pageList(HttpServletRequest request,
@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length, int jobGroup, int jobId, int logStatus,
String filterTime) {
@RequestParam(value = "start", required = false, defaultValue = "0") int start,
@RequestParam(value = "length", required = false, defaultValue = "10") int length,
@RequestParam("jobGroup") int jobGroup, @RequestParam("jobId") int jobId,
@RequestParam("logStatus") int logStatus, @RequestParam("filterTime") String filterTime) {
// valid permission
PermissionInterceptor.validJobGroupPermission(request, jobGroup); // 仅管理员支持查询全部;普通用户仅支持查询有权限的
@@ -130,7 +131,7 @@ public class JobLogController {
}
@RequestMapping("/logDetailPage")
public String logDetailPage(int id, Model model) {
public String logDetailPage(@RequestParam("id") int id, Model model) {
// base check
ReturnT<String> logStatue = ReturnT.SUCCESS;
@@ -147,7 +148,8 @@ public class JobLogController {
@RequestMapping("/logDetailCat")
@ResponseBody
public ReturnT<LogResult> logDetailCat(long logId, int fromLineNum) {
public ReturnT<LogResult> logDetailCat(@RequestParam("logId") long logId,
@RequestParam("fromLineNum") int fromLineNum) {
try {
// valid
XxlJobLog jobLog = xxlJobLogDao.load(logId); // todo, need to improve
@@ -186,7 +188,7 @@ public class JobLogController {
@RequestMapping("/logKill")
@ResponseBody
public ReturnT<String> logKill(int id) {
public ReturnT<String> logKill(@RequestParam("id") int id) {
// base check
XxlJobLog log = xxlJobLogDao.load(id);
XxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());
@@ -223,7 +225,8 @@ public class JobLogController {
@RequestMapping("/clearLog")
@ResponseBody
public ReturnT<String> clearLog(HttpServletRequest request, int jobGroup, int jobId, int type) {
public ReturnT<String> clearLog(HttpServletRequest request, @RequestParam("jobGroup") int jobGroup,
@RequestParam("jobId") int jobId, @RequestParam("type") int type) {
// valid permission
PermissionInterceptor.validJobGroupPermission(request, jobGroup);
@@ -49,8 +49,9 @@ public class JobUserController {
@RequestMapping("/pageList")
@ResponseBody
@PermissionLimit(adminuser = true)
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
@RequestParam(required = false, defaultValue = "10") int length, String username, int role) {
public Map<String, Object> pageList(@RequestParam(value = "start", required = false, defaultValue = "0") int start,
@RequestParam(value = "length", required = false, defaultValue = "10") int length,
@RequestParam("username") String username, @RequestParam("role") int role) {
// page list
List<XxlJobUser> list = xxlJobUserDao.pageList(start, length, username, role);
@@ -140,7 +141,7 @@ public class JobUserController {
@RequestMapping("/remove")
@ResponseBody
@PermissionLimit(adminuser = true)
public ReturnT<String> remove(HttpServletRequest request, int id) {
public ReturnT<String> remove(HttpServletRequest request, @RequestParam("id") int id) {
// avoid opt login seft
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
@@ -154,7 +155,8 @@ public class JobUserController {
@RequestMapping("/updatePwd")
@ResponseBody
public ReturnT<String> updatePwd(HttpServletRequest request, String password, String oldPassword) {
public ReturnT<String> updatePwd(HttpServletRequest request, @RequestParam("password") String password,
@RequestParam("oldPassword") String oldPassword) {
// valid
if (oldPassword == null || oldPassword.trim().length() == 0) {
@@ -55,10 +55,9 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
if (needAdminuser && loginUser.getRole() != 1) {
throw new RuntimeException(I18nUtil.getString("system_permission_limit"));
}
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser); // set
// loginUser,
// with
// request
// set loginUser, with request
setLoginUser(request, loginUser);
}
return true; // proceed with the next interceptor
@@ -66,16 +65,25 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
// -------------------- permission tool --------------------
/**
* set loginUser
* @param request
* @param loginUser
*/
private static void setLoginUser(HttpServletRequest request, XxlJobUser loginUser) {
request.setAttribute("loginUser", loginUser);
}
/**
* get loginUser
* @param request
* @return
*/
public static XxlJobUser getLoginUser(HttpServletRequest request) {
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY); // get
// loginUser,
// with
// request
XxlJobUser loginUser = (XxlJobUser) request.getAttribute("loginUser"); // get
// loginUser,
// with
// request
return loginUser;
}
@@ -25,4 +25,4 @@ public class WebMvcConfig implements WebMvcConfigurer {
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**");
}
}
}
@@ -1,8 +1,8 @@
package com.xxl.job.admin.controller.resolver;
import com.xxl.job.admin.core.exception.XxlJobException;
import com.xxl.job.admin.core.util.JacksonUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.admin.core.util.JacksonUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
@@ -66,4 +66,4 @@ public class WebExceptionResolver implements HandlerExceptionResolver {
}
}
}
}
@@ -60,7 +60,15 @@ public class XxlJobCompleter {
int childJobId = (childJobIds[i] != null && childJobIds[i].trim().length() > 0
&& isNumeric(childJobIds[i])) ? Integer.valueOf(childJobIds[i]) : -1;
if (childJobId > 0) {
// valid
if (childJobId == xxlJobLog.getJobId()) {
logger.debug(
">>>>>>>>>>> xxl-job, XxlJobCompleter-finishJob ignore childJobId, childJobId {} is self.",
childJobId);
continue;
}
// trigger child job
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);
ReturnT<String> triggerChildResult = ReturnT.SUCCESS;
@@ -54,6 +54,9 @@ public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
@Value("${xxl.job.accessToken:}")
private String accessToken;
@Value("${xxl.job.timeout:100}")
private int timeout;
@Value("${spring.mail.from}")
private String emailFrom;
@@ -103,6 +106,10 @@ public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
return accessToken;
}
public int getTimeout() {
return timeout;
}
public String getEmailFrom() {
return emailFrom;
}
@@ -25,9 +25,9 @@
// import org.slf4j.LoggerFactory;
// import org.springframework.util.Assert;
//
// import jakarta.servlet.ServletException;
// import jakarta.servlet.http.HttpServletRequest;
// import jakarta.servlet.http.HttpServletResponse;
// import javax.servlet.ServletException;
// import javax.servlet.http.HttpServletRequest;
// import javax.servlet.http.HttpServletResponse;
// import java.io.IOException;
// import java.util.Date;
// import java.util.concurrent.ConcurrentHashMap;
@@ -427,4 +427,4 @@
// return jobList;
// }*/
//
// }
// }
@@ -92,7 +92,8 @@ public class XxlJobScheduler {
}
// set-cache
executorBiz = new ExecutorBizClient(address, XxlJobAdminConfig.getAdminConfig().getAccessToken());
executorBiz = new ExecutorBizClient(address, XxlJobAdminConfig.getAdminConfig().getAccessToken(),
XxlJobAdminConfig.getAdminConfig().getTimeout());
executorBizRepository.put(address, executorBiz);
return executorBiz;
@@ -65,7 +65,7 @@ public class JobCompleteHelper {
try {
TimeUnit.MILLISECONDS.sleep(50);
}
catch (InterruptedException e) {
catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@@ -95,7 +95,7 @@ public class JobCompleteHelper {
}
}
catch (Exception e) {
catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
@@ -104,7 +104,7 @@ public class JobCompleteHelper {
try {
TimeUnit.SECONDS.sleep(60);
}
catch (Exception e) {
catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@@ -132,7 +132,7 @@ public class JobCompleteHelper {
try {
monitorThread.join();
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@@ -91,7 +91,7 @@ public class JobFailMonitorHelper {
}
}
catch (Exception e) {
catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
@@ -100,7 +100,7 @@ public class JobFailMonitorHelper {
try {
TimeUnit.SECONDS.sleep(10);
}
catch (Exception e) {
catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@@ -124,7 +124,7 @@ public class JobFailMonitorHelper {
try {
monitorThread.join();
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@@ -2,11 +2,13 @@ package com.xxl.job.admin.core.thread;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobLogReport;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
@@ -14,144 +16,155 @@ import java.util.concurrent.TimeUnit;
*
* @author xuxueli 2019-11-22
*/
public class JobLogReportHelper {
private static Logger logger = LoggerFactory.getLogger(JobLogReportHelper.class);
private static Logger logger = LoggerFactory.getLogger(JobLogReportHelper.class);
@Getter
private static JobLogReportHelper instance = new JobLogReportHelper();
private static JobLogReportHelper instance = new JobLogReportHelper();
private Thread logrThread;
public static JobLogReportHelper getInstance() {
return instance;
}
private volatile boolean toStop = false;
private Thread logrThread;
public void start() {
logrThread = new Thread(new Runnable() {
private volatile boolean toStop = false;
@Override
public void run() {
public void start() {
logrThread = new Thread(new Runnable() {
// last clean log time
long lastCleanLogTime = 0;
@Override
public void run() {
while (!toStop) {
// last clean log time
long lastCleanLogTime = 0;
// 1、log-report refresh: refresh log report in 3 days
try {
while (!toStop) {
for (int i = 0; i < 3; i++) {
// 1、log-report refresh: refresh log report in 3 days
try {
// today
Calendar itemDay = Calendar.getInstance();
itemDay.add(Calendar.DAY_OF_MONTH, -i);
itemDay.set(Calendar.HOUR_OF_DAY, 0);
itemDay.set(Calendar.MINUTE, 0);
itemDay.set(Calendar.SECOND, 0);
itemDay.set(Calendar.MILLISECOND, 0);
for (int i = 0; i < 3; i++) {
Date todayFrom = itemDay.getTime();
// today
Calendar itemDay = Calendar.getInstance();
itemDay.add(Calendar.DAY_OF_MONTH, -i);
itemDay.set(Calendar.HOUR_OF_DAY, 0);
itemDay.set(Calendar.MINUTE, 0);
itemDay.set(Calendar.SECOND, 0);
itemDay.set(Calendar.MILLISECOND, 0);
itemDay.set(Calendar.HOUR_OF_DAY, 23);
itemDay.set(Calendar.MINUTE, 59);
itemDay.set(Calendar.SECOND, 59);
itemDay.set(Calendar.MILLISECOND, 999);
Date todayFrom = itemDay.getTime();
Date todayTo = itemDay.getTime();
itemDay.set(Calendar.HOUR_OF_DAY, 23);
itemDay.set(Calendar.MINUTE, 59);
itemDay.set(Calendar.SECOND, 59);
itemDay.set(Calendar.MILLISECOND, 999);
// refresh log-report every minute
XxlJobLogReport xxlJobLogReport = new XxlJobLogReport();
xxlJobLogReport.setTriggerDay(todayFrom);
xxlJobLogReport.setRunningCount(0);
xxlJobLogReport.setSucCount(0);
xxlJobLogReport.setFailCount(0);
Date todayTo = itemDay.getTime();
Map<String, Object> triggerCountMap = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao()
.findLogReport(todayFrom, todayTo);
if (triggerCountMap != null && !triggerCountMap.isEmpty()) {
Map<String, Object> lowerTriggerCountMap = new HashMap<>(triggerCountMap.size());
triggerCountMap.forEach((k, v) -> lowerTriggerCountMap.put(k.toLowerCase(Locale.ROOT), v));
int triggerDayCount = lowerTriggerCountMap.containsKey("triggerdaycount") ? Integer.parseInt(String.valueOf(lowerTriggerCountMap.get("triggerdaycount"))) : 0;
int triggerDayCountRunning = lowerTriggerCountMap.containsKey("triggerdaycountrunning") ? Integer.parseInt(String.valueOf(lowerTriggerCountMap.get("triggerdaycountrunning"))) : 0;
int triggerDayCountSuc = lowerTriggerCountMap.containsKey("triggerdaycountsuc") ? Integer.parseInt(String.valueOf(lowerTriggerCountMap.get("triggerdaycountsuc"))) : 0;
int triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;
// refresh log-report every minute
XxlJobLogReport xxlJobLogReport = new XxlJobLogReport();
xxlJobLogReport.setTriggerDay(todayFrom);
xxlJobLogReport.setRunningCount(0);
xxlJobLogReport.setSucCount(0);
xxlJobLogReport.setFailCount(0);
xxlJobLogReport.setRunningCount(triggerDayCountRunning);
xxlJobLogReport.setSucCount(triggerDayCountSuc);
xxlJobLogReport.setFailCount(triggerDayCountFail);
}
Map<String, Object> triggerCountMap = XxlJobAdminConfig.getAdminConfig()
.getXxlJobLogDao()
.findLogReport(todayFrom, todayTo);
if (triggerCountMap != null && triggerCountMap.size() > 0) {
int triggerDayCount = triggerCountMap.containsKey("triggerDayCount")
? Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCount"))) : 0;
int triggerDayCountRunning = triggerCountMap.containsKey("triggerDayCountRunning")
? Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCountRunning")))
: 0;
int triggerDayCountSuc = triggerCountMap.containsKey("triggerDayCountSuc")
? Integer.valueOf(String.valueOf(triggerCountMap.get("triggerDayCountSuc")))
: 0;
int triggerDayCountFail = triggerDayCount - triggerDayCountRunning - triggerDayCountSuc;
// do refresh
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao()
.update(xxlJobLogReport);
if (ret < 1) {
XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao().save(xxlJobLogReport);
}
}
xxlJobLogReport.setRunningCount(triggerDayCountRunning);
xxlJobLogReport.setSucCount(triggerDayCountSuc);
xxlJobLogReport.setFailCount(triggerDayCountFail);
}
} catch (Exception e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job log report thread error:{}", e);
}
}
// do refresh
int ret = XxlJobAdminConfig.getAdminConfig()
.getXxlJobLogReportDao()
.update(xxlJobLogReport);
if (ret < 1) {
XxlJobAdminConfig.getAdminConfig().getXxlJobLogReportDao().save(xxlJobLogReport);
}
}
// 2、log-clean: switch open & once each day
if (XxlJobAdminConfig.getAdminConfig().getLogretentiondays() > 0
&& System.currentTimeMillis() - lastCleanLogTime > 24 * 60 * 60 * 1000) {
}
catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job log report thread error:{}", e);
}
}
// expire-time
Calendar expiredDay = Calendar.getInstance();
expiredDay.add(Calendar.DAY_OF_MONTH,
-1 * XxlJobAdminConfig.getAdminConfig().getLogretentiondays());
expiredDay.set(Calendar.HOUR_OF_DAY, 0);
expiredDay.set(Calendar.MINUTE, 0);
expiredDay.set(Calendar.SECOND, 0);
expiredDay.set(Calendar.MILLISECOND, 0);
Date clearBeforeTime = expiredDay.getTime();
// 2、log-clean: switch open & once each day
if (XxlJobAdminConfig.getAdminConfig().getLogretentiondays() > 0
&& System.currentTimeMillis() - lastCleanLogTime > 24 * 60 * 60 * 1000) {
// clean expired log
List<Long> logIds = null;
do {
logIds = XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().findClearLogIds(0, 0,
clearBeforeTime, 0, 1000);
if (logIds != null && !logIds.isEmpty()) {
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().clearLog(logIds);
}
}
while (logIds != null && !logIds.isEmpty());
// expire-time
Calendar expiredDay = Calendar.getInstance();
expiredDay.add(Calendar.DAY_OF_MONTH,
-1 * XxlJobAdminConfig.getAdminConfig().getLogretentiondays());
expiredDay.set(Calendar.HOUR_OF_DAY, 0);
expiredDay.set(Calendar.MINUTE, 0);
expiredDay.set(Calendar.SECOND, 0);
expiredDay.set(Calendar.MILLISECOND, 0);
Date clearBeforeTime = expiredDay.getTime();
// update clean time
lastCleanLogTime = System.currentTimeMillis();
}
// clean expired log
List<Long> logIds = null;
do {
logIds = XxlJobAdminConfig.getAdminConfig()
.getXxlJobLogDao()
.findClearLogIds(0, 0, clearBeforeTime, 0, 1000);
if (logIds != null && logIds.size() > 0) {
XxlJobAdminConfig.getAdminConfig().getXxlJobLogDao().clearLog(logIds);
}
}
while (logIds != null && logIds.size() > 0);
try {
TimeUnit.MINUTES.sleep(1);
} catch (Exception e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
// update clean time
lastCleanLogTime = System.currentTimeMillis();
}
}
try {
TimeUnit.MINUTES.sleep(1);
}
catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
}
logger.info(">>>>>>>>>>> xxl-job, job log report thread stop");
}
}
});
logrThread.setDaemon(true);
logrThread.setName("xxl-job, admin JobLogReportHelper");
logrThread.start();
}
logger.info(">>>>>>>>>>> xxl-job, job log report thread stop");
public void toStop() {
toStop = true;
// interrupt and wait
logrThread.interrupt();
try {
logrThread.join();
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
}
});
logrThread.setDaemon(true);
logrThread.setName("xxl-job, admin JobLogReportHelper");
logrThread.start();
}
public void toStop() {
toStop = true;
// interrupt and wait
logrThread.interrupt();
try {
logrThread.join();
}
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
}
@@ -11,7 +11,6 @@ import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@@ -51,7 +50,7 @@ public class JobScheduleHelper {
try {
TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis() % 1000);
}
catch (InterruptedException e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -174,7 +173,7 @@ public class JobScheduleHelper {
// tx stop
}
catch (Exception e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread error:{}", e);
}
@@ -186,7 +185,7 @@ public class JobScheduleHelper {
try {
conn.commit();
}
catch (SQLException e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -194,7 +193,7 @@ public class JobScheduleHelper {
try {
conn.setAutoCommit(connAutoCommit);
}
catch (SQLException e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -202,7 +201,7 @@ public class JobScheduleHelper {
try {
conn.close();
}
catch (SQLException e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -214,7 +213,7 @@ public class JobScheduleHelper {
try {
preparedStatement.close();
}
catch (SQLException e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -231,7 +230,7 @@ public class JobScheduleHelper {
TimeUnit.MILLISECONDS
.sleep((preReadSuc ? 1000 : PRE_READ_MS) - System.currentTimeMillis() % 1000);
}
catch (InterruptedException e) {
catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -258,7 +257,7 @@ public class JobScheduleHelper {
try {
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
}
catch (InterruptedException e) {
catch (Throwable e) {
if (!ringThreadToStop) {
logger.error(e.getMessage(), e);
}
@@ -288,7 +287,7 @@ public class JobScheduleHelper {
ringItemData.clear();
}
}
catch (Exception e) {
catch (Throwable e) {
if (!ringThreadToStop) {
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
}
@@ -302,10 +301,11 @@ public class JobScheduleHelper {
ringThread.start();
}
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) {
try {
Date nextValidTime = generateNextValidTime(jobInfo, fromTime);
if (nextValidTime != null) {
jobInfo.setTriggerStatus(-1); // pass, may be Inaccurate
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
jobInfo.setTriggerNextTime(nextValidTime.getTime());
}
@@ -319,7 +319,7 @@ public class JobScheduleHelper {
jobInfo.getId(), jobInfo.getScheduleType(), jobInfo.getScheduleConf());
}
}
catch (Exception e) {
catch (Throwable e) {
// generateNextValidTime error, stop job
jobInfo.setTriggerStatus(0);
jobInfo.setTriggerLastTime(0);
@@ -351,7 +351,7 @@ public class JobScheduleHelper {
try {
TimeUnit.SECONDS.sleep(1); // wait
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
if (scheduleThread.getState() != Thread.State.TERMINATED) {
@@ -360,7 +360,7 @@ public class JobScheduleHelper {
try {
scheduleThread.join();
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@@ -380,7 +380,7 @@ public class JobScheduleHelper {
try {
TimeUnit.SECONDS.sleep(8);
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@@ -390,7 +390,7 @@ public class JobScheduleHelper {
try {
TimeUnit.SECONDS.sleep(1);
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
if (ringThread.getState() != Thread.State.TERMINATED) {
@@ -399,7 +399,7 @@ public class JobScheduleHelper {
try {
ringThread.join();
}
catch (InterruptedException e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@@ -27,19 +27,33 @@ public class JobTriggerPoolHelper {
public void start() {
fastTriggerPool = new ThreadPoolExecutor(10, XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax(), 60L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000), new ThreadFactory() {
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(2000), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode());
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
logger.error(
">>>>>>>>>>> xxl-job, admin JobTriggerPoolHelper-fastTriggerPool execute too fast, Runnable="
+ r.toString());
}
});
slowTriggerPool = new ThreadPoolExecutor(10, XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax(), 60L,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(2000), new ThreadFactory() {
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(5000), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode());
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
logger.error(
">>>>>>>>>>> xxl-job, admin JobTriggerPoolHelper-slowTriggerPool execute too fast, Runnable="
+ r.toString());
}
});
}
@@ -81,7 +95,7 @@ public class JobTriggerPoolHelper {
XxlJobTrigger.trigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam,
addressList);
}
catch (Exception e) {
catch (Throwable e) {
logger.error(e.getMessage(), e);
}
finally {
@@ -105,6 +119,11 @@ public class JobTriggerPoolHelper {
}
}
@Override
public String toString() {
return "Job Runnable, jobId:" + jobId;
}
});
}
@@ -92,4 +92,4 @@ public class CookieUtil {
}
}
}
}
@@ -36,8 +36,22 @@ public interface XxlJobInfoDao {
public int findAllCount();
/**
* find schedule job, limit "trigger_status = 1"
* @param maxNextTime
* @param pagesize
* @return
*/
public List<XxlJobInfo> scheduleJobQuery(@Param("maxNextTime") long maxNextTime, @Param("pagesize") int pagesize);
/**
* update schedule job
*
* 1、can only update "trigger_status = 1", Avoid stopping tasks from being opened
* 2、valid "triggerStatus gte 0", filter illegal state
* @param xxlJobInfo
* @return
*/
public int scheduleUpdate(XxlJobInfo xxlJobInfo);
}
@@ -6,12 +6,12 @@ import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.core.util.JacksonUtil;
import com.xxl.job.admin.dao.XxlJobUserDao;
import com.xxl.job.core.biz.model.ReturnT;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.math.BigInteger;
/**
@@ -18,11 +18,11 @@ 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 jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.text.MessageFormat;
import java.util.*;
@@ -269,7 +269,15 @@ public class XxlJobServiceImpl implements XxlJobService {
String[] childJobIds = jobInfo.getChildJobId().split(",");
for (String childJobIdItem : childJobIds) {
if (childJobIdItem != null && childJobIdItem.trim().length() > 0 && isNumeric(childJobIdItem)) {
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem));
// parse child
int childJobId = Integer.parseInt(childJobIdItem);
if (childJobId == jobInfo.getId()) {
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_childJobId")
+ "(" + childJobId + ")" + I18nUtil.getString("system_unvalid")));
}
// valid child
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(childJobId);
if (childJobInfo == null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId") + "({0})"
@@ -1,6 +1,6 @@
admin_name=Scheduling Center
admin_name_full=Distributed Task Scheduling Platform XXL-JOB
admin_version=2.5.0-SNAPSHOT
admin_version=3.0.0
admin_i18n=en
## system
@@ -1,6 +1,6 @@
admin_name=任务调度中心
admin_name_full=分布式任务调度平台XXL-JOB
admin_version=2.5.0-SNAPSHOT
admin_version=3.0.0
admin_i18n=
## system
@@ -1,6 +1,6 @@
admin_name=任務調度中心
admin_name_full=分布式任務調度平臺XXL-JOB
admin_version=2.5.0-SNAPSHOT
admin_version=3.0.0
admin_i18n=
## system
@@ -69,7 +69,7 @@
</logger>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<root level="debug">
<appender-ref ref="console"/>
<appender-ref ref="debug"/>
<appender-ref ref="error"/>
@@ -16,12 +16,12 @@ $(function(){
userName : {
required : true ,
minlength: 4,
maxlength: 18
maxlength: 20
},
password : {
required : true ,
minlength: 4,
maxlength: 18
maxlength: 20
}
},
messages : {
@@ -32,7 +32,7 @@ $(function(){
password : {
required : I18n.login_password_empty ,
minlength : I18n.login_password_lt_4
/*,maxlength:"登录密码不应超过18位"*/
/*,maxlength:"登录密码不应超过20位"*/
}
},
highlight : function(element) {
@@ -17,7 +17,7 @@
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/dist/css/AdminLTE.min.css">
<!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. -->
<link rel="stylesheet" href="${request.contextPath}/static/adminlte/dist/css/skins/_all-skins.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
@@ -84,7 +84,7 @@
<#-- login user -->
<li class="dropdown">
<a href="javascript:" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
${I18n.system_welcome} ${XXL_JOB_LOGIN_IDENTITY.username}
${I18n.system_welcome} ${loginUser.username}
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
@@ -141,7 +141,7 @@
<li class="nav-click <#if pageName == "index">active</#if>" ><a href="${request.contextPath}/"><i class="fa fa-circle-o text-aqua"></i><span>${I18n.job_dashboard_name}</span></a></li>
<li class="nav-click <#if pageName == "jobinfo">active</#if>" ><a href="${request.contextPath}/jobinfo"><i class="fa fa-circle-o text-yellow"></i><span>${I18n.jobinfo_name}</span></a></li>
<li class="nav-click <#if pageName == "joblog">active</#if>" ><a href="${request.contextPath}/joblog"><i class="fa fa-circle-o text-green"></i><span>${I18n.joblog_name}</span></a></li>
<#if XXL_JOB_LOGIN_IDENTITY.role == 1>
<#if loginUser.role == 1>
<li class="nav-click <#if pageName == "jobgroup">active</#if>" ><a href="${request.contextPath}/jobgroup"><i class="fa fa-circle-o text-red"></i><span>${I18n.jobgroup_name}</span></a></li>
<li class="nav-click <#if pageName == "user">active</#if>" ><a href="${request.contextPath}/user"><i class="fa fa-circle-o text-purple"></i><span>${I18n.user_manage}</span></a></li>
</#if>
@@ -176,7 +176,7 @@
</a>
</li>
<li>
<a href="javascript::;">
<a href="javascript::;">
<i class="menu-icon fa fa-user bg-yellow"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Frodo 更新了资料</h4>
@@ -185,7 +185,7 @@
</a>
</li>
<li>
<a href="javascript::;">
<a href="javascript::;">
<i class="menu-icon fa fa-envelope-o bg-light-blue"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Nora 加入邮件列表</h4>
@@ -240,4 +240,4 @@
</strong><!-- All rights reserved. -->
</div>
</footer>
</#macro>
</#macro>
@@ -15,14 +15,14 @@
<@netCommon.commonHeader />
<!-- left -->
<@netCommon.commonLeft "joblog" />
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>${I18n.joblog_name}</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
@@ -30,7 +30,7 @@
<div class="input-group">
<span class="input-group-addon">${I18n.jobinfo_field_jobgroup}</span>
<select class="form-control" id="jobGroup" paramVal="<#if jobInfo?exists>${jobInfo.jobGroup}</#if>" >
<#if XXL_JOB_LOGIN_IDENTITY.role == 1>
<#if loginUser.role == 1>
<option value="0" >${I18n.system_all}</option> <#-- 仅管理员支持查询全部;普通用户仅支持查询有权限的 jobGroup -->
</#if>
<#list JobGroupList as group>
@@ -77,7 +77,7 @@
<button class="btn btn-block btn-default" id="clearLog">${I18n.joblog_clean}</button>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
@@ -108,7 +108,7 @@
</div>
</section>
</div>
<!-- footer -->
<@netCommon.commonFooter />
</div>
@@ -15,11 +15,11 @@
<div class="login-box-body">
<p class="login-box-msg">${I18n.admin_name}</p>
<div class="form-group has-feedback">
<input type="text" name="userName" class="form-control" placeholder="${I18n.login_username_placeholder}" maxlength="18" >
<input type="text" name="userName" class="form-control" placeholder="${I18n.login_username_placeholder}" maxlength="20" >
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" name="password" class="form-control" placeholder="${I18n.login_password_placeholder}" maxlength="18" >
<input type="password" name="password" class="form-control" placeholder="${I18n.login_password_placeholder}" maxlength="20" >
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
+1 -1
View File
@@ -56,7 +56,7 @@
<jaxb.version>2.3.5</jaxb.version>
<jimu.version>1.8.1</jimu.version>
<aws.version>1.12.261</aws.version>
<xxl.job.version>2.4.2</xxl.job.version>
<xxl.job.version>3.0.0</xxl.job.version>
<docker.registry>registry.cn-hangzhou.aliyuncs.com</docker.registry>
<docker.host>http://127.0.0.1:2375</docker.host>
<docker.namespace>pigcloudx</docker.namespace>