首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >完成后重置计划作业

完成后重置计划作业
EN

Stack Overflow用户
提问于 2021-09-07 06:00:36
回答 3查看 99关注 0票数 0

我有一个使用Spring batch实现的计划作业。现在,当它完成时,它不会再次启动,因为它被检测为已完成,是否可以在完成后重置其状态?

代码语言:javascript
复制
@Component
class JobScheduler {

    @Autowired
    private Job job1;

    @Autowired
    private JobLauncher jobLauncher;

    @Scheduled(cron = "0 0/15 * * * ?")
    public void launchJob1() throws Exception {
        this.jobLauncher.run(this.job1, new JobParameters());
    }
}

@Configuration
public class Job1Configuration{

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job job1() {
        return this.jobBuilderFactory.get("job1")
            .start(this.step1()).on(STEP1_STATUS.NOT_READY.get()).end()
            .from(this.step1()).on(STEP1_STATUS.READY.get()).to(this.step2())
            .next(this.step3())
            .end()
            .build();
    }
}

我知道我可以使用时间或id设置作业参数,但这将每15分钟启动一次新的执行。我想重复相同的执行,直到没有错误地完成,然后执行一个新的。

EN

回答 3

Stack Overflow用户

发布于 2021-09-08 00:52:08

您无法重新启动作业,因为您正在通过调用.start(this.step1()).on(STEP1_STATUS.NOT_READY.get()).end()中的end()将作业状态设置为COMPLETE

相反,您应该通过调用.start(this.step1()).on(STEP1_STATUS.NOT_READY.get()).fail()来使作业失败(

或者通过调用.start(this.step1()).on(STEP1_STATUS.NOT_READY.get()).stopAndRestart(step1())来停止作业

这些选项将意味着作业状态是FAILEDSTOPPED,而不是COMPLETE,这意味着如果您使用相同的JobParameters启动作业,它将在上一次作业执行时重新启动。

请参阅https://docs.spring.io/spring-batch/docs/current/reference/html/step.html#configuringForStop

要以处理重新启动以前的实例或启动新实例的方式启动作业,您可以查看SimpleJobService -batch-admin中的批处理是如何执行的,并根据您的目的稍微修改一下启动方法。这要求您指定一个增量作业参数,该参数用于启动作业的新实例。

https://github.com/spring-attic/spring-batch-admin/blob/master/spring-batch-admin-manager/src/main/java/org/springframework/batch/admin/service/SimpleJobService.java#L250

代码语言:javascript
复制
   @Override
    public JobExecution launch(String jobName, JobParameters jobParameters) throws NoSuchJobException,
            JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException,
            JobParametersInvalidException {

        JobExecution jobExecution = null;

        if (jobLocator.getJobNames().contains(jobName)) {
            Job job = jobLocator.getJob(jobName);

            JobExecution lastJobExecution = jobRepository.getLastJobExecution(jobName, jobParameters);
            boolean restart = false;
            if (lastJobExecution != null) {
                BatchStatus status = lastJobExecution.getStatus();
                if (status.isUnsuccessful() && status != BatchStatus.ABANDONED) {
                    restart = true;
                }
            }

            if (job.getJobParametersIncrementer() != null && !restart) {
                jobParameters = job.getJobParametersIncrementer().getNext(jobParameters);
            }

            jobExecution = jobLauncher.run(job, jobParameters);

            if (jobExecution.isRunning()) {
                activeExecutions.add(jobExecution);
            }
        } else {
            if (jsrJobOperator != null) {
//                jobExecution = this.jobExecutionDao
//                        .getJobExecution(jsrJobOperator.start(jobName, jobParameters.toProperties()));
                jobExecution = new JobExecution(jsrJobOperator.start(jobName, jobParameters.toProperties()));
            } else {
                throw new NoSuchJobException(String.format("Unable to find job %s to launch",
                        String.valueOf(jobName)));
            }
        }

        return jobExecution;
    }
票数 1
EN

Stack Overflow用户

发布于 2021-09-08 05:09:16

这是我在所有评论之后想出的解决方案:

代码语言:javascript
复制
@Component
class JobScheduler extends JobSchedulerLauncher {

    @Autowired
    private Job job1;

    @Scheduled(cron = "0 0/15 * * * ?")
    public void launchJob1() throws Exception {
        this.launch(this.job1);
    }
}

public abstract class JobSchedulerLauncher {

    @Autowired
    private JobOperator jobOperator;

    @Autowired
    private JobExplorer jobExplorer;

    public void launch(Job job) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException,
        JobParametersInvalidException, NoSuchJobException, NoSuchJobExecutionException, JobExecutionNotRunningException, JobParametersNotFoundException, UnexpectedJobExecutionException {

        // Get the last instance
        final List<JobInstance> jobInstances = this.jobExplorer.findJobInstancesByJobName(job.getName(), 0, 1);
        if (CollectionUtils.isNotEmpty(jobInstances)) {
            // Get the last executions
            final List<JobExecution> jobExecutions = this.jobExplorer.getJobExecutions(jobInstances.get(0));

            if (CollectionUtils.isNotEmpty(jobExecutions)) {
                final JobExecution lastJobExecution = jobExecutions.get(0);
                if (lastJobExecution.isRunning()) {
                    this.jobOperator.stop(lastJobExecution.getId().longValue());
                    this.jobOperator.abandon(lastJobExecution.getId().longValue());
                } else if (lastJobExecution.getExitStatus().equals(ExitStatus.FAILED) || lastJobExecution.getExitStatus().equals(ExitStatus.STOPPED)) {
                    this.jobOperator.restart(lastJobExecution.getId().longValue());
                    return;
                }
            }
        }

        this.jobOperator.startNextInstance(job.getName());
    }
}

我的工作现在使用了一个增量器,基于这个https://docs.spring.io/spring-batch/docs/current/reference/html/job.html#JobParametersIncrementer

代码语言:javascript
复制
@Bean
public Job job1() {
    return this.jobBuilderFactory.get("job1")
        .incrementer(new CustomJobParameterIncrementor())
        .start(this.step1()).on(STEP1_STATUS.NOT_READY.get()).end()
        .from(this.step1()).on(STEP1_STATUS.READY.get()).to(this.step2())
        .next(this.step3())
        .end()
        .build();
}

在我的例子中,我的调度程序不会同时启动同一作业的两个实例,所以如果我在这段代码中检测到一个正在运行的作业,这意味着服务器重新启动了该作业,并将其状态保留为已启动,这就是我停止它并放弃它的原因。

票数 0
EN

Stack Overflow用户

发布于 2021-09-08 08:32:05

我认为这里的困难来自于混合调度和可重启性。我会让每个调度执行一个不同的作业实例(例如,通过添加运行时作为识别作业参数)。

现在,如果给定的计划失败,它可以单独重新启动,直到完成,而不会影响后续计划。这可以手动完成,也可以在另一个预定的方法中以编程方式完成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69083064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档