package com.github.ltsopensource.jobtracker.complete;
import com.github.ltsopensource.biz.logger.domain.JobLogPo;
import com.github.ltsopensource.biz.logger.domain.LogType;
import com.github.ltsopensource.core.commons.utils.CollectionUtils;
import com.github.ltsopensource.core.constant.Constants;
import com.github.ltsopensource.core.constant.Level;
import com.github.ltsopensource.core.domain.JobMeta;
import com.github.ltsopensource.core.domain.JobRunResult;
import com.github.ltsopensource.core.json.JSON;
import com.github.ltsopensource.core.logger.Logger;
import com.github.ltsopensource.core.logger.LoggerFactory;
import com.github.ltsopensource.core.support.CronExpressionUtils;
import com.github.ltsopensource.core.support.JobDomainConverter;
import com.github.ltsopensource.core.support.JobUtils;
import com.github.ltsopensource.core.support.SystemClock;
import com.github.ltsopensource.jobtracker.domain.JobTrackerAppContext;
import com.github.ltsopensource.queue.domain.JobPo;
import com.github.ltsopensource.store.jdbc.exception.DupEntryException;
import java.util.Date;
import java.util.List;
/**
* @author Robert HG (254963746@qq.com) on 11/11/15.
*/
public class JobFinishHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(JobFinishHandler.class);
private JobTrackerAppContext appContext;
public JobFinishHandler(JobTrackerAppContext appContext) {
this.appContext = appContext;
}
public void onComplete(List<JobRunResult> results) {
if (CollectionUtils.isEmpty(results)) {
return;
}
for (JobRunResult result : results) {
JobMeta jobMeta = result.getJobMeta();
// 当前完成的job是否是重试的
boolean isRetryForThisTime = Boolean.TRUE.toString().equals(jobMeta.getInternalExtParam(Constants.IS_RETRY_JOB));
boolean isOnce = Boolean.TRUE.toString().equals(jobMeta.getInternalExtParam(Constants.ONCE));
if (jobMeta.getJob().isCron()) {
// 是 Cron任务
if (isOnce) {
finishNoReplyPrevCronJob(jobMeta);
} else {
finishCronJob(jobMeta.getJobId());
}
} else if (jobMeta.getJob().isRepeatable()) {
if (isOnce) {
finishNoReplyPrevRepeatJob(jobMeta, isRetryForThisTime);
} else {
finishRepeatJob(jobMeta.getJobId(), isRetryForThisTime);
}
}
// 从正在执行的队列中移除
appContext.getExecutingJobQueue().remove(jobMeta.getJobId());
}
}
private void finishCronJob(String jobId) {
JobPo jobPo = appContext.getCronJobQueue().getJob(jobId);
if (jobPo == null) {
// 可能任务队列中改条记录被删除了
return;
}
Date nextTriggerTime = CronExpressionUtils.getNextTriggerTime(jobPo.getCronExpression());
if (nextTriggerTime == null) {
// 从CronJob队列中移除
appContext.getCronJobQueue().remove(jobId);
jobRemoveLog(jobPo, "Cron");
return;
}
// 表示下次还要执行
try {
jobPo.setTaskTrackerIdentity(null);
jobPo.setIsRunning(false);
jobPo.setTriggerTime(nextTriggerTime.getTime());
jobPo.setGmtModified(SystemClock.now());
jobPo.setInternalExtParam(Constants.EXE_SEQ_ID, JobUtils.generateExeSeqId(jobPo));
appContext.getExecutableJobQueue().add(jobPo);
} catch (DupEntryException e) {
LOGGER.warn("ExecutableJobQueue already exist:" + JSON.toJSONString(jobPo));
}
}
private void finishNoReplyPrevCronJob(JobMeta jobMeta) {
JobPo jobPo = appContext.getCronJobQueue().getJob(jobMeta.getJob().getTaskTrackerNodeGroup(), jobMeta.getRealTaskId());
if (jobPo == null) {
// 可能任务队列中改条记录被删除了
return;
}
Date nextTriggerTime = CronExpressionUtils.getNextTriggerTime(jobPo.getCronExpression());
if (nextTriggerTime == null) {
// 检查可执行队列中是否还有
if (appContext.getExecutableJobQueue().countJob(jobPo.getRealTaskId(), jobPo.getTaskTrackerNodeGroup()) == 0) {
// TODO 检查执行中队列是否还有
// 从CronJob队列中移除
appContext.getCronJobQueue().remove(jobPo.getJobId());
jobRemoveLog(jobPo, "Cron");
}
}
}
private void finishNoReplyPrevRepeatJob(JobMeta jobMeta, boolean isRetryForThisTime) {
JobPo jobPo = appContext.getRepeatJobQueue().getJob(jobMeta.getJob().getTaskTrackerNodeGroup(), jobMeta.getRealTaskId());
if (jobPo == null) {
// 可能任务队列中改条记录被删除了
return;
}
if (jobPo.getRepeatCount() != -1 && jobPo.getRepeatedCount() >= jobPo.getRepeatCount()) {
// 已经重试完成, 那么删除, 这里可以不用check可执行队列是否还有,因为这里依赖的是计数
appContext.getRepeatJobQueue().remove(jobPo.getJobId());
jobRemoveLog(jobPo, "Repeat");
return;
}
// 如果当前完成的job是重试的,那么不要增加repeatedCount
if (!isRetryForThisTime) {
// 更新repeatJob的重复次数
appContext.getRepeatJobQueue().incRepeatedCount(jobPo.getJobId());
}
}
private void finishRepeatJob(String jobId, boolean isRetryForThisTime) {
JobPo jobPo = appContext.getRepeatJobQueue().getJob(jobId);
if (jobPo == null) {
// 可能任务队列中改条记录被删除了
return;
}
if (jobPo.getRepeatCount() != -1 && jobPo.getRepeatedCount() >= jobPo.getRepeatCount()) {
// 已经重试完成, 那么删除
appContext.getRepeatJobQueue().remove(jobId);
jobRemoveLog(jobPo, "Repeat");
return;
}
int repeatedCount = jobPo.getRepeatedCount();
// 如果当前完成的job是重试的,那么不要增加repeatedCount
if (!isRetryForThisTime) {
// 更新repeatJob的重复次数
repeatedCount = appContext.getRepeatJobQueue().incRepeatedCount(jobId);
}
if (repeatedCount == -1) {
// 表示任务已经被删除了
return;
}
long nexTriggerTime = JobUtils.getRepeatNextTriggerTime(jobPo);
try {
jobPo.setRepeatedCount(repeatedCount);
jobPo.setTaskTrackerIdentity(null);
jobPo.setIsRunning(false);
jobPo.setTriggerTime(nexTriggerTime);
jobPo.setGmtModified(SystemClock.now());
jobPo.setInternalExtParam(Constants.EXE_SEQ_ID, JobUtils.generateExeSeqId(jobPo));
appContext.getExecutableJobQueue().add(jobPo);
} catch (DupEntryException e) {
LOGGER.warn("ExecutableJobQueue already exist:" + JSON.toJSONString(jobPo));
}
}
private void jobRemoveLog(JobPo jobPo, String type) {
JobLogPo jobLogPo = JobDomainConverter.convertJobLog(jobPo);
jobLogPo.setSuccess(true);
jobLogPo.setLogType(LogType.DEL);
jobLogPo.setLogTime(SystemClock.now());
jobLogPo.setLevel(Level.INFO);
jobLogPo.setMsg(type + " Job Finished");
appContext.getJobLogger().log(jobLogPo);
}
}