Comment déclencher et arrêter un travail par lots programmé de printemps

Comment déclencher et arrêter un travail par lots de printemps programmé

1. Vue d'ensemble

Dans ce didacticiel, nous étudierons et comparerons différentes manières detrigger and stop a scheduled Spring Batch job  pour les analyses de rentabilisation requises.

Si vous avez besoin de présentations sur Spring Batch et Scheduler, veuillez vous référer aux articlesSpring-Batch etSpring-Scheduler.

2. Déclencher un travail par lots de printemps planifié

Premièrement, nous avons une classeSpringBatchScheduler pour configurer la planification et le travail par lots. Une méthodelaunchJob() sera enregistrée en tant que tâche planifiée.

De plus, pour déclencher la tâche Spring Batch planifiée de la manière la plus intuitive, ajoutons un indicateur conditionnel pour déclencher la tâche uniquement lorsque l'indicateur est défini sur true:

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)

La variablebatchRunCounter sera utilisée dans les tests d'intégration pour vérifier si le travail par lots a été arrêté.

3. Arrêter un travail par lots de printemps planifié

Avec l'indicateur conditionnel ci-dessus, nous pouvons déclencher la tâche Spring Batch planifiée avec la tâche planifiée active.

Si nous n'avons pas besoin de reprendre la tâche, nous pouvons en fait arrêter la tâche planifiée pour économiser des ressources.

Jetons un coup d'œil à deux options dans les deux sous-sections suivantes.

3.1. Utilisation du post-processeur du planificateur

Puisque nous planifions une méthode en utilisant l'annotation@Scheduled, un post-processeur de haricotsScheduledAnnotationBeanPostProcessor aurait été enregistré en premier.

Nous pouvons appeler explicitement lespostProcessBeforeDestruction() pour détruire le bean planifié donné:

@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());
}

Compte tenu de plusieurs planificateurs, il est préférable de conserver un planificateur dans sa propre classe, afin que nous puissions arrêter un planificateur spécifique si nécessaire.

3.2. Annulation desFuture programmés

Une autre façon d'arrêter le planificateur serait d'annuler manuellement sesFuture.

Voici un planificateur de tâches personnalisé pour capturer la carte 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;
    }
}

Ensuite, nous itérons la carteFuture et annulons lesFuture pour notre planificateur de travaux par lots:

public void cancelFutureSchedulerTasks() {
    scheduledTasks.forEach((k, v) -> {
        if (k instanceof SpringBatchScheduler) {
            v.cancel(false);
        }
    });
}

Dans les cas avec plusieurs tâches de planificateur, nous pouvons alors maintenir la carteFuture à l'intérieur du pool de planificateur personnalisé mais annuler lesFuture planifiés correspondants en fonction de la classe du planificateur.

4. Conclusion

Dans cet article rapide, nous avons essayé trois méthodes différentes pour déclencher ou arrêter un travail Spring Batch planifié.

Lorsque nous devons redémarrer le travail par lots, l’utilisation d’un indicateur conditionnel pour gérer l’exécution du travail constitue une solution flexible. Sinon, nous pouvons suivre les deux autres options pour arrêter complètement le planificateur.

Comme d'habitude, tous les exemples de code utilisés dans l'article sont disponiblesover on GitHub.