Рубрики
Без рубрики

Как запустить и остановить запланированное пакетное задание Spring

Изучите три различных способа запуска и остановки запланированного весеннего пакетного задания.

Автор оригинала: baeldung.

1. Обзор

В этом руководстве мы рассмотрим и сравним различные способы запуска и остановки запланированного пакетного задания Spring для любых необходимых бизнес-кейсов.

Если вам нужны сведения о Spring Batch и планировщике, пожалуйста, обратитесь к статьям Spring-Batch и Spring-Scheduler.

2. Запуск запланированного весеннего пакетного задания

Во-первых, у нас есть класс Spring Batch Scheduler для настройки планирования и пакетного задания. Метод launchJob() будет зарегистрирован как запланированная задача.

Кроме того, чтобы запустить запланированное пакетное задание Spring наиболее интуитивно понятным способом, давайте добавим условный флаг для запуска задания только тогда, когда флаг установлен в 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)

Переменная счетчик выполнения пакета будет использоваться в интеграционных тестах для проверки того, было ли остановлено пакетное задание.

3. Остановите запланированное пакетное задание Spring

С помощью вышеприведенного условного флага мы можем запустить запланированное пакетное задание Spring с включенной запланированной задачей.

Если нам не нужно возобновлять работу, мы можем фактически остановить запланированную задачу, чтобы сэкономить ресурсы.

Давайте рассмотрим два варианта в следующих двух подразделах.

3.1. Использование Планировщика Постпроцессор

Поскольку мы планируем метод с помощью @Scheduled аннотации, бобовый постпроцессор ScheduledAnnotationBeanPostProcessor был бы зарегистрирован первым.

Мы можем явно вызвать postProcessBeforeDestruction () , чтобы уничтожить данный запланированный компонент:

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

Учитывая несколько планировщиков, лучше сохранить один планировщик в своем собственном классе, чтобы мы могли останавливать конкретный планировщик по мере необходимости.

3.2. Отмена запланированного будущего

Другой способ остановить планировщик-вручную отменить его Будущее .

Вот пользовательский планировщик задач для захвата Будущего карты:

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

Затем мы повторяем Future map и отменяем Future для нашего планировщика пакетных заданий:

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

В случаях с несколькими задачами планировщика мы можем сохранить карту Future внутри пользовательского пула планировщиков, но отменить соответствующий запланированный Future на основе класса планировщика.

4. Заключение

В этой краткой статье мы попробовали три различных способа запуска или остановки запланированного пакетного задания Spring.

Когда нам нужно перезапустить пакетное задание, использование условного флага для управления запуском задания было бы гибким решением. В противном случае мы можем следовать двум другим вариантам, чтобы полностью остановить планировщик.

Как обычно, все примеры кода, используемые в статье, доступны на GitHub .