Como acionar e interromper um trabalho em lote agendado da primavera
1. Visão geral
Neste tutorial, vamos investigar e comparar diferentes maneiras detrigger and stop a scheduled Spring Batch job para quaisquer casos de negócios necessários.
Se você precisar de introduções sobre Spring Batch and Scheduler, consulte os artigosSpring-BatcheSpring-Scheduler.
2. Disparar um trabalho em lote programado de primavera
Primeiramente, temos uma classeSpringBatchScheduler para configurar o agendamento e o batch job. Um métodolaunchJob() será registrado como uma tarefa agendada.
Além disso, para acionar o trabalho agendado do Spring Batch da maneira mais intuitiva, vamos adicionar um sinalizador condicional para disparar o trabalho apenas quando o sinalizador estiver definido como verdadeiro:
private AtomicBoolean enabled = new AtomicBoolean(true);
private AtomicInteger batchRunCounter = new AtomicInteger(0);
@Scheduled(fixedRate = 2000)
public void launchJob() throws Exception {
if (enabled.get()) {
Date date = new Date();
JobExecution jobExecution = jobLauncher()
.run(job(), new JobParametersBuilder()
.addDate("launchDate", date)
.toJobParameters());
batchRunCounter.incrementAndGet();
}
}
// stop, start functions (changing the flag of enabled)
A variávelbatchRunCounter será usada em testes de integração para verificar se o trabalho em lote foi interrompido.
3. Interromper um trabalho em lote agendado da primavera
Com o sinalizador condicional acima, podemos acionar o job agendado do Spring Batch com a tarefa agendada ativa.
Se não precisarmos retomar o trabalho, podemos realmente interromper a tarefa agendada para economizar recursos.
Vamos dar uma olhada em duas opções nas próximas duas subseções.
3.1. Usando o processador posterior do agendador
Como estamos agendando um método usando a anotação@Scheduled, um pós-processador de beanScheduledAnnotationBeanPostProcessor teria sido registrado primeiro.
Podemos chamar explicitamente opostProcessBeforeDestruction() para destruir o bean programado fornecido:
@Test
public void stopJobSchedulerWhenSchedulerDestroyed() throws Exception {
ScheduledAnnotationBeanPostProcessor bean = context
.getBean(ScheduledAnnotationBeanPostProcessor.class);
SpringBatchScheduler schedulerBean = context
.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(
2,
schedulerBean.getBatchRunCounter().get()));
bean.postProcessBeforeDestruction(
schedulerBean, "SpringBatchScheduler");
await().atLeast(3, SECONDS);
Assert.assertEquals(
2,
schedulerBean.getBatchRunCounter().get());
}
Considerando vários agendadores, é melhor manter um agendador em sua própria classe, para que possamos interromper o agendador específico conforme necessário.
3.2. Cancelando oFuture programado
Outra maneira de parar o planejador seria cancelar manualmente seuFuture.
Aqui está um programador de tarefas personalizado para capturar o mapa deFuture:
@Bean
public TaskScheduler poolScheduler() {
return new CustomTaskScheduler();
}
private class CustomTaskScheduler
extends ThreadPoolTaskScheduler {
//
@Override
public ScheduledFuture> scheduleAtFixedRate(
Runnable task, long period) {
ScheduledFuture> future = super
.scheduleAtFixedRate(task, period);
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
scheduledTasks.put(runnable.getTarget(), future);
return future;
}
}
Em seguida, iteramos o mapaFuture e cancelamosFuture para nosso agendador de tarefas em lote:
public void cancelFutureSchedulerTasks() {
scheduledTasks.forEach((k, v) -> {
if (k instanceof SpringBatchScheduler) {
v.cancel(false);
}
});
}
Nos casos com várias tarefas do planejador, podemos manter o mapaFuture dentro do pool do planejador personalizado, mas cancelar o correspondenteFuture planejado com base na classe do planejador.
4. Conclusão
Neste artigo, tentamos três maneiras diferentes de acionar ou interromper um trabalho agendado do Spring Batch.
Quando precisamos reiniciar o trabalho em lotes, o uso de um sinalizador condicional para gerenciar a execução do trabalho seria uma solução flexível. Caso contrário, podemos seguir as outras duas opções para parar completamente o planejador.
Como de costume, todos os exemplos de código usados no artigo estão disponíveisover on GitHub.