package com.github.ltsopensource.admin.web.api; import com.github.ltsopensource.admin.cluster.BackendAppContext; import com.github.ltsopensource.admin.request.JobQueueReq; import com.github.ltsopensource.admin.response.PaginationRsp; import com.github.ltsopensource.admin.web.AbstractMVC; import com.github.ltsopensource.admin.web.support.Builder; import com.github.ltsopensource.admin.web.vo.RestfulResponse; import com.github.ltsopensource.biz.logger.JobLogUtils; import com.github.ltsopensource.biz.logger.domain.LogType; import com.github.ltsopensource.core.commons.utils.Assert; import com.github.ltsopensource.core.commons.utils.StringUtils; import com.github.ltsopensource.core.constant.Constants; import com.github.ltsopensource.core.logger.Logger; import com.github.ltsopensource.core.logger.LoggerFactory; import com.github.ltsopensource.core.support.JobUtils; import com.github.ltsopensource.core.support.SystemClock; import com.github.ltsopensource.queue.domain.JobPo; import com.github.ltsopensource.store.jdbc.exception.DupEntryException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Date; /** * @author Robert HG (254963746@qq.com) on 3/26/16. */ @RestController public class RepeatJobQueueApi extends AbstractMVC { private static final Logger LOGGER = LoggerFactory.getLogger(RepeatJobQueueApi.class); @Autowired private BackendAppContext appContext; @RequestMapping("/job-queue/repeat-job-get") public RestfulResponse repeatJobGet(JobQueueReq request) { PaginationRsp<JobPo> paginationRsp = appContext.getRepeatJobQueue().pageSelect(request); RestfulResponse response = new RestfulResponse(); response.setSuccess(true); response.setResults(paginationRsp.getResults()); response.setRows(paginationRsp.getRows()); return response; } @RequestMapping("/job-queue/repeat-job-update") public RestfulResponse repeatJobUpdate(JobQueueReq request) { // 检查参数 try { Assert.hasLength(request.getJobId(), "jobId不能为空!"); Assert.notNull(request.getRepeatInterval(), "repeatInterval不能为空!"); Assert.isTrue(request.getRepeatInterval() > 0, "repeatInterval必须大于0"); Assert.isTrue(request.getRepeatCount() >= -1, "repeatCount必须>= -1"); } catch (IllegalArgumentException e) { return Builder.build(false, e.getMessage()); } request.setCronExpression(null); JobPo oldJobPo = appContext.getRepeatJobQueue().getJob(request.getJobId()); boolean success = appContext.getRepeatJobQueue().selectiveUpdateByJobId(request); if (success) { try { JobPo newJobPo = appContext.getRepeatJobQueue().getJob(request.getJobId()); boolean relyOnPrevCycleChanged = !newJobPo.getRelyOnPrevCycle().equals(oldJobPo.getRelyOnPrevCycle()); // repeatInterval变了或者repeatCount变少了 boolean repeatIntervalChanged = !newJobPo.getRepeatInterval().equals(oldJobPo.getRepeatInterval()); boolean repeatIntervalOrCountDecChanged = repeatIntervalChanged || ( (oldJobPo.getRepeatCount() == -1 && newJobPo.getRepeatCount() > 0) || (oldJobPo.getRepeatCount() != -1 && newJobPo.getRepeatCount() != -1 && newJobPo.getRepeatCount() < oldJobPo.getRepeatCount() ) ); if (oldJobPo.getRelyOnPrevCycle() && !relyOnPrevCycleChanged) { // 如果repeatInterval有修改,需要把triggerTime也要修改下 if (repeatIntervalChanged) { long nextTriggerTime = JobUtils.getRepeatNextTriggerTime(oldJobPo); request.setTriggerTime(new Date(nextTriggerTime)); } // 把等待执行的队列也更新一下 appContext.getExecutableJobQueue().selectiveUpdateByJobId(request); } else { // 2. 需要对批量任务做处理 if (relyOnPrevCycleChanged) { if (oldJobPo.getRelyOnPrevCycle()) { // 之前是依赖的,现在不依赖,需要生成批量任务 appContext.getExecutableJobQueue().remove(oldJobPo.getTaskTrackerNodeGroup(), oldJobPo.getJobId()); appContext.getNoRelyJobGenerator().generateRepeatJobForInterval(newJobPo, new Date()); } else { // 之前不依赖,现在依赖,需要删除批量任务 appContext.getExecutableJobQueue().removeBatch(oldJobPo.getRealTaskId(), oldJobPo.getTaskTrackerNodeGroup()); // 添加新的任务 newJobPo.setTriggerTime(JobUtils.getRepeatNextTriggerTime(oldJobPo)); try { newJobPo.setInternalExtParam(Constants.EXE_SEQ_ID, JobUtils.generateExeSeqId(newJobPo)); appContext.getExecutableJobQueue().add(newJobPo); } catch (DupEntryException ignored) { } } } else { // 如果relyOnPrevCycle 没有修改过, 表示relyOnPrevCycle=false, 那么要看repeatIntervalOrCountDecChanged,如果修改过,需要删除重新生成 if (repeatIntervalOrCountDecChanged) { appContext.getExecutableJobQueue().removeBatch(oldJobPo.getRealTaskId(), oldJobPo.getTaskTrackerNodeGroup()); appContext.getNoRelyJobGenerator().generateRepeatJobForInterval(newJobPo, new Date()); } else { appContext.getExecutableJobQueue().selectiveUpdateByTaskId(request); } } } } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Builder.build(false, "更新等待执行的任务失败,请手动更新! error:" + e.getMessage()); } JobLogUtils.log(LogType.UPDATE, oldJobPo, appContext.getJobLogger()); return Builder.build(true); } else { return Builder.build(false, "该任务已经被删除或者执行完成"); } } @RequestMapping("/job-queue/repeat-job-delete") public RestfulResponse repeatJobDelete(JobQueueReq request) { if (StringUtils.isEmpty(request.getJobId())) { return Builder.build(false, "JobId 必须传!"); } JobPo jobPo = appContext.getRepeatJobQueue().getJob(request.getJobId()); boolean success = appContext.getRepeatJobQueue().remove(request.getJobId()); if (success) { try { appContext.getExecutableJobQueue().removeBatch(jobPo.getRealTaskId(), jobPo.getTaskTrackerNodeGroup()); // appContext.getExecutableJobQueue().remove(request.getTaskTrackerNodeGroup(), request.getJobId()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Builder.build(false, "删除等待执行的任务失败,请手动删除! error:{}" + e.getMessage()); } } JobLogUtils.log(LogType.DEL, jobPo, appContext.getJobLogger()); return Builder.build(true); } @RequestMapping("/job-queue/repeat-job-suspend") public RestfulResponse repeatJobSuspend(JobQueueReq request) { if (StringUtils.isEmpty(request.getJobId())) { return Builder.build(false, "JobId 必须传!"); } JobPo jobPo = appContext.getRepeatJobQueue().getJob(request.getJobId()); if (jobPo == null) { return Builder.build(false, "任务不存在,或者已经删除"); } try { jobPo.setGmtModified(SystemClock.now()); appContext.getSuspendJobQueue().add(jobPo); } catch (DupEntryException e) { LOGGER.error(e.getMessage(), e); return Builder.build(false, "该任务已经被暂停, 请检查暂停队列"); } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Builder.build(false, "移动任务到暂停队列失败, error:" + e.getMessage()); } try { appContext.getRepeatJobQueue().remove(request.getJobId()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Builder.build(false, "删除Repeat任务失败,请手动删除! error:" + e.getMessage()); } try { if (!jobPo.getRelyOnPrevCycle()) { appContext.getRepeatJobQueue().updateLastGenerateTriggerTime(jobPo.getJobId(), new Date().getTime()); appContext.getExecutableJobQueue().removeBatch(jobPo.getRealTaskId(), jobPo.getTaskTrackerNodeGroup()); } else { appContext.getExecutableJobQueue().remove(request.getTaskTrackerNodeGroup(), request.getJobId()); } } catch (Exception e) { LOGGER.error(e.getMessage(), e); return Builder.build(false, "删除等待执行的任务失败,请手动删除! error:" + e.getMessage()); } JobLogUtils.log(LogType.SUSPEND, jobPo, appContext.getJobLogger()); return Builder.build(true); } }