Остановить все весенние пакетные задания при завершении работы (CTRL-C)JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Остановить все весенние пакетные задания при завершении работы (CTRL-C)

Сообщение Anonymous »

У меня есть приложение Spring Boot/Spring Batch, которое запускает разные задания.
Когда приложение остановлено () задания остаются в рабочем состоянии (STARTED).

Несмотря на то, что сочетание клавиш CTRL-C дает приложению достаточно времени для корректной остановки заданий, результат тот же, что и уничтожение -9.
Я нашел способ (см. ниже) корректно остановить все задания, когда приложение завершается с помощью CTRL-C, но хотелось бы знать, есть ли лучший/более простой способ достичь этой цели.
Все, что приведено ниже, представляет собой документацию о том, как мне удалось остановить задания. p>
В записи блога 부알프레도 JobExecutionListener используется для регистрации перехватчиков завершения работы, которые должны останавливать задания:

Код: Выделить всё

public class ProcessShutdownListener implements JobExecutionListener {
private final JobOperator jobOperator;
ProcessShutdownListener(JobOperator jobOperator) { this.jobOperator = jobOperator; }

@Override public void afterJob(JobExecution jobExecution) { /* do nothing. */ }

@Override
public void beforeJob(final JobExecution jobExecution) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
super.run();
try {
jobOperator.stop(jobExecution.getId());
while(jobExecution.isRunning()) {
try { Thread.sleep(100); } catch (InterruptedException e) {}
}
} catch (NoSuchJobExecutionException | JobExecutionNotRunningException e) { /* ignore */ }
}
});
}
}
В дополнение к предоставленному коду мне также пришлось создать JobRegistryBeanPostProcessor.

Без этого PostProcessor jobOperator не смог бы найти работу.

(

Код: Выделить всё

NoSuchJobException: No job configuration with the name [job1] was registered

Код: Выделить всё

    @Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}
Хук завершения работы не смог записать состояние в базу данных, поскольку соединение с базой данных уже было закрыто:

Код: Выделить всё

org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL)

Код: Выделить всё

Processing item 2 before
Shutdown Hook is running !
2021-02-08 22:39:48.950  INFO 12676 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2021-02-08 22:39:49.218  INFO 12676 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
Processing item 3 before
Exception in thread "Thread-3" org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30004ms.
Чтобы убедиться, что весенняя загрузка не закрывает пул источников данных hikari до остановки заданий, я использовал SmartLifeCycle, как упоминалось здесь.
Окончательный ProcessShutdownListener выглядит так:

Код: Выделить всё

@Component
public class ProcessShutdownListener implements JobExecutionListener, SmartLifecycle {
private final JobOperator jobOperator;
public ProcessShutdownListener(JobOperator jobOperator) { this.jobOperator = jobOperator; }

@Override
public void afterJob(JobExecution jobExecution) { /* do nothing.  */ }

private static final List runnables = new ArrayList();

@Override
public void beforeJob(final JobExecution jobExecution) {
runnables.add(() -> {
try {
if (!jobOperator.stop(jobExecution.getId())) return;
while (jobExecution.isRunning()) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) { /* ignore */ }
}
} catch (NoSuchJobExecutionException | JobExecutionNotRunningException e) { /* ignore */ }
});
}

@Override
public void start() {}

@Override
public void stop() {
//        runnables.stream()
//                .parallel()
//                .forEach(Runnable::run);
runnables.forEach(Runnable::run);
}

@Override
public boolean isRunning() { return true; }

@Override
public boolean isAutoStartup() { return true; }

@Override
public void stop(Runnable callback) { stop(); callback.run(); }

@Override
public int getPhase() { return Integer.MAX_VALUE; }
}
Этот прослушиватель должен быть зарегистрирован при настройке задания:

Код: Выделить всё

    @Bean
public Job job(JobBuilderFactory jobs,
ProcessShutdownListener processShutdownListener) {
return jobs.get("job1")
.listener(processShutdownListener)
.start(step(null))
.build();
}
Наконец, как указано в выводе исключения, к URL-адресу jdbc необходимо добавить флаг: ;DB_CLOSE_ON_EXIT=FALSE.


Подробнее здесь: https://stackoverflow.com/questions/661 ... own-ctrl-c
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как остановить фоновые задачи при корректном завершении работы FastAPI
    Anonymous » » в форуме Python
    0 Ответы
    30 Просмотры
    Последнее сообщение Anonymous
  • Пакетные задания Laravel застряли на горизонте
    Anonymous » » в форуме Php
    0 Ответы
    43 Просмотры
    Последнее сообщение Anonymous
  • Есть ли смысл использовать пакетные скрипты вместо Python для работы с ОС?
    Гость » » в форуме Python
    0 Ответы
    22 Просмотры
    Последнее сообщение Гость
  • RuntimeError: невозможно создать новый поток при завершении работы интерпретатора
    Anonymous » » в форуме Python
    0 Ответы
    42 Просмотры
    Последнее сообщение Anonymous
  • Как автоматически заставить приложение iOS останавливать таймер/GPS при завершении работы приложения – Flutter
    Anonymous » » в форуме IOS
    0 Ответы
    19 Просмотры
    Последнее сообщение Anonymous

Вернуться в «JAVA»