某些作业比我们的调度程序间隔运行的时间更长。跳过这些工作是非常安全的。如何检测具有相同名称和参数(运行时间除外)的作业当前是否正在运行?
Quartz将Batch作业运行为:
import org.springframework.batch.core.JobParametersBuilder;
@Override
protected void executeInternal(org.quartz.JobExecutionContext context) {
Map<String, Object> jobDataMap = context.getMergedJobDataMap();
String jobName = (String) jobDataMap.get("job.name");
JobParametersBuilder builder = new JobParametersBuilder();
builder.addString("company", jobDataMap.get("company"));
builder.addDate("run.date", new Date());
try {
jobLauncher.run(jobLocator.getJob(jobName), jobParametersBuilder.toJobParameters());
}
catch (JobExecutionException e) {
log.error("Could not execute job.", e);
}
}
我需要查找特定"job.name"
/ "company"
(无论"run.date"
)的任何执行是否正在运行。
我可以使用针对BATCH_
表运行的普通SQL来实现这一点。
检查应该在Tasklet中运行,以便JobRepository可以自动装配。是否可以仅使用JobRepository
或其他Spring Batch bean找到它?
答案 0 :(得分:0)
您可以从识别中排除“run.date”。
使用公开JobParameter(Date parameter, boolean identifying)
来自JobParameter的文档。
识别标志用于指示参数是否是 用作识别作业实例的一部分。
所以只需添加不带builder.addDate("run.date", new Date());
的参数并运行作业。
答案 1 :(得分:0)
我的解决方案基于JobExplorer.findRunningJobExecutions()
(找到最新未完成的工作):
/**
* If there are jobs with same parameters, that started later then some number we can run new job again.
*
* {@link JobExplorer#findRunningJobExecutions(String)} selects jobs with BATCH_JOB_EXECUTION.END_TIME is null.
*
* @return null if there is no jobs with same parameters, otherwise the latest running.
*/
public JobExecution getLatestRunningJob(JobExplorer jobExplorer, String jobName, String agency, String branch) {
long now = new Date().getTime();
long minDiff = Long.MAX_VALUE;
JobExecution latestExecution = null;
Set<JobExecution> runningJobs = jobExplorer.findRunningJobExecutions(jobName);
for (JobExecution execution : Optional.ofNullable(runningJobs).orElse(Collections.emptySet())) {
JobParameters params = execution.getJobParameters();
// log.warn("agencyName {}", params.getString("agencyName"));
// log.warn("branchName {}", params.getString("branchName"));
if ( ! agency.equals(params.getString("agencyName")))
continue;
if ( ! branch.equals(params.getString("branchName")))
continue;
// log.warn("create {}", execution.getCreateTime());
// log.warn("start {}", execution.getStartTime());
long diff = now - execution.getCreateTime().getTime();
if (diff < 0) {
log.warn("Impossible, new job executed before old! Old JobExecution id: {}", execution.getJobId());
continue;
}
if (diff < minDiff) {
minDiff = diff;
latestExecution = execution;
}
}
return latestExecution;
}
和决策者:
/**
* @param execution not null
* @param limitMinutes how long job should be runnning to ignore
*/
public boolean canIgnoreLateJob(JobExecution execution, long limitMinutes) {
long now = new Date().getTime();
long diffMinutes = TimeUnit.MINUTES.convert(now - execution.getCreateTime().getTime(), TimeUnit.MILLISECONDS);
if (diffMinutes < limitMinutes) {
log.warn("Recent JobExecution {} is still not finished, can't run new job, diff (minute): {}",
execution.getJobId(), diffMinutes);
return false;
} else {
log.warn("Very old JobExecution {} is still not finished, can run new job, diff (minute): {}",
execution.getJobId(), diffMinutes);
return true;
}
}
此解决方案的缺点是JobExplorer
解析JobExecution中的每个字段(包括所有步骤)。所以表现并不完美。但解决方案是可靠的。