Как можно перезапустить весенний пакет с определенной точки, если он внезапно заканчивается

Прочитав много о перезапуске в Spring Batch, я узнал, что:

  • SB может перезапустить шаг с самого начала, когда задание не удалось. Пример: Задание 1 -> шаг 1, шаг 2, шаг 3 (НЕУДАЧА) -> затем можно перезапустить с шага 3.

Я хотел бы другое поведение, но я не нашел решения, которое мне подходит.

У меня есть работа с одним шагом. Этот шаг читает текстовый файл (может иметь много строк). Я хочу защитить нашу систему на случай непредвиденного завершения (например, внезапное отключение нашего сервера). В этом случае, если мы прочитали X строк, я хочу восстановить задание с X + 1 строк до конца.

¿Можно ли этого достичь?

Заранее спасибо.


person Pabloch    schedule 24.02.2021    source источник
comment
Да и поддерживается "из коробки". Вам необходимо включить сохранение метаданных при выполнении задания. Затем, если шаг завершился неудачно (или прерван), он продолжится с того места, откуда он ушел.   -  person M. Deinum    schedule 24.02.2021
comment
@MahmoudBenHassine да, это помогает. Часть перезапуска с использованием идентификатора хороша. Но если процесс резко завершается, статус остается НАЧАЛО. Я мог бы перезапуститься из состояния установки точки FAILED в работу и шаг. Есть ли способ перезапустить без изменения статуса в базе данных?   -  person Pabloch    schedule 25.02.2021
comment
There is any way to restart without manipulate status in database? : Нет, Spring Batch просматривает состояние репозитория заданий перед запуском/перезапуском любого задания, и если он находит выполнение задания как STARTED, он будет думать, что выполняется выполнение (хотя его нет). Ручной процесс описан здесь: stackoverflow.com/a/66211982/5019386. Если вы хотите автоматизировать это, вам нужно написать собственный код, который обнаруживает, что задание было внезапно уничтожено (я действительно не понимаю, как это возможно), и обновляет репозиторий заданий с помощью показанных запросов sql.   -  person Mahmoud Ben Hassine    schedule 25.02.2021
comment
Спасибо, @MahmoudBenHassine. Возможно, нам нужно запускать этот пакет только один раз в день, поэтому, возможно, мы можем проверить, был ли он убит, просмотрев, был ли пакет ЗАПУЩЕН в течение слишком долгого времени (но это зависит от того, как долго будет наш входной файл...)   -  person Pabloch    schedule 25.02.2021
comment
Это может сработать, если вы четко определяете слишком много времени.   -  person Mahmoud Ben Hassine    schedule 25.02.2021


Ответы (1)


IMO, если задание резко останавливается на строке X, а вы хотите начать со строки X+1, это произойдет, только если размер фрагмента равен 1. Поскольку, когда размер фрагмента равен 1, каждая обработанная запись фиксируется, и JobContext точно знает, когда это не удалось и откуда перезапустить.

Когда размер вашего фрагмента больше 1, скажем, 8, и ваша работа резко останавливается, когда обрабатывался элемент 4, тогда первые 3 элемента, обработанные в фрагменте, также не фиксируются в таблицах выполнения задания во время сбоя и контекста начнется с того же фрагмента из 1-й записи. В этом случае вы снова обработаете первые 3 элемента!

Этого можно избежать, если вы включите корректное завершение задания Spring Batch, когда происходит прерывание ядра, чтобы блок был полностью обработан до завершения процесса. Это сведет к минимуму количество зарегистрированных инцидентов, но все равно будут такие шансы, как - когда вилка питания вашего сервера отключена, и у программы нет возможности выполнить корректное завершение работы.

Предложения:

  1. Если процесс идемпотентный, нет проблем, если некоторые элементы обрабатываются повторно.
  2. Если процесс не является идемпотентным, вероятно, в CompositeProcessor может быть помещена какая-то проверка на удаление дубликатов.

Для корректного закрытия задания я написал код PoC. Вы можете увидеть это здесь — https://github.com/innovationchef/batchpay/blob/master/src/main/java/com/innovationchef/batchcommons/JobManager.java

person Innovationchef    schedule 24.02.2021
comment
IMO, if the job stops abruptly at line X and you want to start at line X+1, it will happen only if the chunk size is 1. Если chunkSize=1 и задание резко останавливается на строке X, то строка X будет повторно обработана при перезапуске (поскольку на этой строке произошла ошибка, и ее транзакция была отменена). Таким образом, задание будет перезапущено в строке X, а не в строке X+1. - person Mahmoud Ben Hassine; 25.02.2021
comment
@Innovationchef спасибо за ваш код, он очень понятный и полезный. Но у меня есть сомнения. Чтобы проверить, выполняется ли задание, весенняя пакетная проверка, если start_date не равна нулю, и если end_date равна нулю (незавершенный процесс). Но это не решает проблему резкого конца. Я решил, установив end_date вручную (мне это не нравится, но я не знаю альтернативы). И для проверки возможности перезапуска задания вы сравниваете статус с ОСТАНОВЛЕНО. Мое предыдущее сомнение может быть применено здесь. Что произойдет, если статус останется НАЧАЛО? - person Pabloch; 25.02.2021
comment
@Pabloch Я думаю, что мы ни по какой причине не должны сами обновлять пакетные таблицы. Вот почему пользователям предоставляется объект JobExplorer отдельно от JobRepository. Возвращаясь к вашему вопросу - что делать, если статус остается НАЧАЛО? -› Вы уже знаете, в каких состояниях он может находиться, и у вас могут быть свои собственные определения выключения и перезапуска прививки. Мой код — это просто POC, где я пытался отправить SIGINT через ядро ​​​​и проверить, работают ли основные вещи или нет. - person Innovationchef; 25.02.2021