首页 > 解决方案 > Spring-batch 步骤未重新执行(缓存)

问题描述

我正在开发一个包含 Spring 批处理的项目,在复制代码片段之前,我将简单地总结一下这项工作是如何与 cron 一起工作的。

  1. cron 在我的项目上调用了一个 rest API (@PostMapping("/jobs/external/{jobName}"))
  2. 在 post 方法中,我得到了工作并执行它。
  3. 在每次执行中,我应该运行一个步骤。
  4. 该步骤包含一个阅读器(对弹性 API 的外部休息调用以获取文档)和一个处理器。

现在我的问题是:在cron 中catalina.out,我可以每隔 10 分钟看到一次来自 cron 的其余调用,如我的 cron 中配置的那样。但是,该步骤似乎不是每 10 分钟调用一次弹性,批处理始终具有相同的数据集,在 tomcat 重新启动期间调用批处理时会获取一次。

工作休息api:

@PostMapping("/jobs/external/{jobName}")
@Timed
public ResponseEntity start(@PathVariable String jobName) throws BatchException {
    log.info("LAUNCHING JOB FROM EXTERNAL : {}, timestamp : {}", jobName, Instant.now().toString());
    try {
        Job job = jobRegistry.getJob(jobName);
        JobParametersBuilder builder = new JobParametersBuilder();
        builder.addDate("date", new Date());
        return Optional.of(jobLauncher.run(job, builder.toJobParameters()))
            .map(BatchExecutionVM::new)
            .map(exec -> ResponseEntity
                .ok()
                .headers(HeaderUtil.createAlert("jobManagement.started", jobName))
                .body(exec))
            .orElseGet(() -> ResponseEntity.badRequest().build());
    } catch (NoSuchJobException aEx) {
        log.warn(JOB_NOT_FOUND, aEx);
        throw new BatchException();
    } catch (JobInstanceAlreadyCompleteException | JobExecutionAlreadyRunningException | JobRestartException aEx) {
        log.warn("Job execution error.", aEx);
        throw new BatchException();
    } catch (JobParametersInvalidException aEx) {
        log.warn("Job parameters are invalid.", aEx);
        throw new BatchException();
    }
}

作业配置:

@Bean
public Job usualJob() {
    return jobBuilderFactory
        .get("usualJob")
        .incrementer(new SimpleJobIncrementer())
        .flow(readUsualStep())
        .end()
        .build();
}

@Bean
public Step readUsualStep() {
    // TODO: simplifier on n'a pas besoin de chunk
    return stepBuilderFactory.get("readUsualStep")
        .allowStartIfComplete(true)
        .<AlertDocument, Void>chunk(25)
        .readerIsTransactionalQueue()
        .reader(rowItemReader())
        .processor(rowItemProcessor())
        .build();
}
@Bean
public ItemReader<AlertDocument> rowItemReader() {
    return new UsualItemReader(usualService.getLastAlerts());
}
@Bean
public UsualMapRowProcessor rowItemProcessor() {
    return new UsualMapRowProcessor();
}

我不知道为什么usualService.getLastAlerts()只调用一次而不是每 10 分钟调用一次。

标签: springspring-batch

解决方案


感谢 M. Deinum,这基本上是解决方案:

    @Bean
@StepScope
public ItemReader<AlertDocument> rowItemReader() {
    return new UsualItemReader(usualService.getLastAlerts());
}

使用 stepScope 注释对 step bean 进行注释将使其每一步都重新实例化。


推荐阅读