查找 spring 个已存在 X 天的批处理实例
Finding spring batch instances which are X days old
目前我已经重新启动 spring-batch
作业,每小时 运行 并通过 JobExplorer
检查数据库以查找失败的作业实例,它会为作业选择最新的作业实例失败并重新启动最新的执行。这工作正常,但我们现在有新的请求,不仅要重启最新的实例,还要重启 X
天 window 内的所有实例,我们应该从最旧的实例开始重新启动一个实例,直到它脱离这个 window.
示例:
- 作业
A
的实例 jobInstance1
在晚上 8 点失败
- 作业
A
的实例 jobInstance2
在晚上 9 点失败
- 第一次重启在晚上 10 点开始,第一次重启
jobInstance1
jobInstance1
现在成功
- 重启在晚上 11 点第二次开始并重启
jobInstance2
我在考虑两个方案:
- 使用
JobExplorer
以及 List<JobInstance> getJobInstances(String jobName, int start, int count);
和 int getJobInstanceCount(String jobName) throws NoSuchJobException;
的组合,并通过检查开始时间遍历列表以找到我要查找的内容
- 扩展
JdbcJobInstanceDao
并编写我自己的针对 JOB_INSTANCE
的查询 table 加入 JOB_EXECUTION
并使用
是否有更好的方法来获取某个作业的所有失败作业实例,这些实例最多存在 3 天,并将它们排在最前面?
如果没有更好的方法,您如何看待选项1和2?
我最终按照 Michael Minella 的建议编写了自己的 JobInstanceDao
。我只在重新启动作业中需要它,所以我没有扩展 spring 第一批,但我使用 spring 第一批作为示例。如果有人需要,这里是实现:
package com.custom.package;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.joda.time.DateTime;
import org.springframework.batch.core.JobInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class CustomJobInstanceDao {
public static final String BATCH_TABLE_PREFIX = "BATCH";
private static final String GET_JOBS_WITH_STATUS_AFTER_DATE = "SELECT ji.JOB_INSTANCE_ID, ji.JOB_NAME FROM %PREFIX%_JOB_EXECUTION je LEFT JOIN %PREFIX%_JOB_INSTANCE ji "
+ " ON je.JOB_INSTANCE_ID = ji.JOB_INSTANCE_ID WHERE ji.JOB_NAME = ? AND je.STATUS = ? AND je.START_TIME > ? GROUP BY je.JOB_INSTANCE_ID";
private static final String GET_RUNNING_JOBS_AFTER_DATE = "SELECT ji.JOB_INSTANCE_ID, ji.JOB_NAME FROM %PREFIX%_JOB_EXECUTION je LEFT JOIN %PREFIX%_JOB_INSTANCE ji "
+ " ON je.JOB_INSTANCE_ID = ji.JOB_INSTANCE_ID WHERE ji.JOB_NAME = ? AND je.END_TIME is NULL AND je.START_TIME > ? GROUP BY je.JOB_INSTANCE_ID";
@Autowired
private JdbcTemplate jdbcTemplate;
public List<JobInstance> getJobInstancesWithStatusAfterStartDate(final String jobName, final String status,
final DateTime afterStartTime) {
return jdbcTemplate.query(getQuery(GET_JOBS_WITH_STATUS_AFTER_DATE), new Object[] {jobName, status,
afterStartTime.toDate()}, new JobInstanceRowMapper());
}
public List<JobInstance> getRunningJobInstancesAfterStartDate(final String jobName, final DateTime afterStartTime) {
return jdbcTemplate.query(getQuery(GET_RUNNING_JOBS_AFTER_DATE),
new Object[] {jobName, afterStartTime.toDate()}, new JobInstanceRowMapper());
}
private String getQuery(final String base) {
return StringUtils.replace(base, "%PREFIX%", BATCH_TABLE_PREFIX);
}
private final class JobInstanceRowMapper implements ParameterizedRowMapper<JobInstance> {
public JobInstanceRowMapper() {
}
@Override
public JobInstance mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final JobInstance jobInstance = new JobInstance(rs.getLong(1), rs.getString(2));
// should always be at version=0 because they never get updated
jobInstance.incrementVersion();
return jobInstance;
}
}
}
目前我已经重新启动 spring-batch
作业,每小时 运行 并通过 JobExplorer
检查数据库以查找失败的作业实例,它会为作业选择最新的作业实例失败并重新启动最新的执行。这工作正常,但我们现在有新的请求,不仅要重启最新的实例,还要重启 X
天 window 内的所有实例,我们应该从最旧的实例开始重新启动一个实例,直到它脱离这个 window.
示例:
- 作业
A
的实例jobInstance1
在晚上 8 点失败 - 作业
A
的实例jobInstance2
在晚上 9 点失败 - 第一次重启在晚上 10 点开始,第一次重启
jobInstance1
jobInstance1
现在成功- 重启在晚上 11 点第二次开始并重启
jobInstance2
我在考虑两个方案:
- 使用
JobExplorer
以及List<JobInstance> getJobInstances(String jobName, int start, int count);
和int getJobInstanceCount(String jobName) throws NoSuchJobException;
的组合,并通过检查开始时间遍历列表以找到我要查找的内容 - 扩展
JdbcJobInstanceDao
并编写我自己的针对JOB_INSTANCE
的查询 table 加入JOB_EXECUTION
并使用
是否有更好的方法来获取某个作业的所有失败作业实例,这些实例最多存在 3 天,并将它们排在最前面?
如果没有更好的方法,您如何看待选项1和2?
我最终按照 Michael Minella 的建议编写了自己的 JobInstanceDao
。我只在重新启动作业中需要它,所以我没有扩展 spring 第一批,但我使用 spring 第一批作为示例。如果有人需要,这里是实现:
package com.custom.package;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.joda.time.DateTime;
import org.springframework.batch.core.JobInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
public class CustomJobInstanceDao {
public static final String BATCH_TABLE_PREFIX = "BATCH";
private static final String GET_JOBS_WITH_STATUS_AFTER_DATE = "SELECT ji.JOB_INSTANCE_ID, ji.JOB_NAME FROM %PREFIX%_JOB_EXECUTION je LEFT JOIN %PREFIX%_JOB_INSTANCE ji "
+ " ON je.JOB_INSTANCE_ID = ji.JOB_INSTANCE_ID WHERE ji.JOB_NAME = ? AND je.STATUS = ? AND je.START_TIME > ? GROUP BY je.JOB_INSTANCE_ID";
private static final String GET_RUNNING_JOBS_AFTER_DATE = "SELECT ji.JOB_INSTANCE_ID, ji.JOB_NAME FROM %PREFIX%_JOB_EXECUTION je LEFT JOIN %PREFIX%_JOB_INSTANCE ji "
+ " ON je.JOB_INSTANCE_ID = ji.JOB_INSTANCE_ID WHERE ji.JOB_NAME = ? AND je.END_TIME is NULL AND je.START_TIME > ? GROUP BY je.JOB_INSTANCE_ID";
@Autowired
private JdbcTemplate jdbcTemplate;
public List<JobInstance> getJobInstancesWithStatusAfterStartDate(final String jobName, final String status,
final DateTime afterStartTime) {
return jdbcTemplate.query(getQuery(GET_JOBS_WITH_STATUS_AFTER_DATE), new Object[] {jobName, status,
afterStartTime.toDate()}, new JobInstanceRowMapper());
}
public List<JobInstance> getRunningJobInstancesAfterStartDate(final String jobName, final DateTime afterStartTime) {
return jdbcTemplate.query(getQuery(GET_RUNNING_JOBS_AFTER_DATE),
new Object[] {jobName, afterStartTime.toDate()}, new JobInstanceRowMapper());
}
private String getQuery(final String base) {
return StringUtils.replace(base, "%PREFIX%", BATCH_TABLE_PREFIX);
}
private final class JobInstanceRowMapper implements ParameterizedRowMapper<JobInstance> {
public JobInstanceRowMapper() {
}
@Override
public JobInstance mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final JobInstance jobInstance = new JobInstance(rs.getLong(1), rs.getString(2));
// should always be at version=0 because they never get updated
jobInstance.incrementVersion();
return jobInstance;
}
}
}