Создание и запуск пакетной обработки

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

Подготовка при помощи BatchBuilder

\Drupal\Core\Batch\BatchBuilder — объект, позволяющий строить очередь для последующего запуска.

Пример:

$data_to_process = [
  ['foo', 'bar'],
  ['baz'],
];

$batch = new BatchBuilder();
$batch
  ->setTitle(new TranslatableMarkup('My batch'))
  ->setInitMessage(new TranslatableMarkup('Prepare operations for processing.'));

foreach ($data_to_process as $data) {
  $batch->addOperation([$this, 'processData'], $data);
}

setTitle()

Метод setTitle() позволяет указать заголовок операции.

Пример:

$batch->setTitle(new TranslatableMarkup('My batch'));

setInitMessage()

Метод setInitMessage() позволяет задать сообщение показываемое при инициализации батча. По умолчанию "Initialazing.".

$batch->setInitMessage(new TranslatableMarkup('Prepare operations for processing.'));

setProgressMessage()

Метод setProgressMessage() позволяет задать сообщение о текущем состоянии выполнения операций.

Вы можете использовать в сообщении следующие подстановки:

  • @current: Текущая операция находящаяся в обработке.
  • @remaining: Количество операций оставшихся для обработки.
  • @total: Общее количество операций в текущей пакетной обработке.
  • @percentage: Процентное отображение выполнения операций.
  • @estimate: Приблизительное время до завершения выполнения всех операций.
  • @elapsed: Время, затраченное на выполнение операций к текущему моменту.

Сообщение прогресса обновляться в конце каждого вызова обработки операции, будь он в одной операции разделенный на несколько вызовов, или несколько различных операций. Это значит, что сообщение показывается после выполнения, а не в процессе. Например, если операций 10, сейчас выполняется 3-ая по списку, а сообщение имеет вид @current of @total, то пользователю будет показано 2 of 10, и только после завершения 3 операции, или её первой итерации, оно заменится на 3 of 10.

Пример:

$batch->setProgressMessage(new Translatablemarkup('Processing @current of @total. Estimated time to finish is @estimate.'))

setErrorMessage()

Метод setErrorMessage() позволяет задать сообщение, которое будет показана в случае возникновении ошибки. По умолчанию "An error has occurred.".

Пример:

$batch->setErrorMessage(new TranslatableMarkup('Contact site administrator.'));

setFile()

Метод setFile() позволяет указать файл, который необходимо подгрузить в процессе обработки операций. По умолчанию, подгружается файл {module_name}.module.

Путь должен быть указан относительно корня ядра.

Пример:

$path_to_file = drupal_get_path('module', 'my_module') . '/my_module.batch.inc';
$batch->setFile($path_to_file);

setLibraries()

Метод setLibraries() позволяет задать список библиотек, которые будут загружены на странице обработки.

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

Пример:

$libraries = [
  'my_module/library_name',
  'my_theme/library_name',
];
$batch->setLibraries($libraries);

setUrlOptions()

Метод setUrlOptions() позволяет задать опции для Url, на который будет переадресован пользователь для выполнения операций.

Путь для всех операций всегда один, но вы можете влиять на передаваемые опции в соответствии с Drupal\Core\Url. Для более детальной информации, какие опции могут быть переданы, обратитесь к документации Url::fromUri().

Пример:

$url_options = [
  'query' => [
    'key' => 'value',
  ],
];
$batch->seetUrlOptions($url_options);

setProgressive()

Метод setProgressive() позволяет включать или отключать прогрессивный режим обработки. По умолчанию данный режим включен.

Прогрессивный режим обработки означает, что операции будут выполняться при помощи вызова множества новых запросов. Отключение прогрессивного режима означает, что будет предпринята попытка выполнить все операции в пределах одного HTTP-запроса. Если по каким-то причинам, обработка операций не успеет завершиться, например, из-за тайм-аута, то вся обработки закончится с ошибкой. Поэтому, отключать прогрессивный режим не рекомендуется без острой необходимости. Это один из плюсов использования пакетной обработки.

Пример:

// Disable progressive mode.
$batch->setProgressive(FALSE);

setQueue()

Метод setQueue() позволяет задать свой собственный идентификатор очереди и класс обработчик.

Принимает два аргумента:

  • $name: Собственное название очереди, которое будет использовано для операций заданных в текущей пакетной обработке.
  • $class: Полное имя класса, ответственного за работу с очередью. Класс должен реализовывать Drupal\Core\Queue\QueueInterface. По умолчанию используется \Drupal\Core\Queue\Batch для прогрессивных обработок и \Drupal\Core\Queue\BatchMemory для операций за один запрос.

Может пригодиться в каких-то специфичных кейсах, когда, например, данные на обработку нужно вынести за пределы БД (memcache, redis или вовсе на иной сервер). Для более подробной информации, рекомендуется изучить материал очередей.

addOperation()

Метод addOperation() позволяет добавлять операции для пакетной обработки.

Метод принимает два аргумента:

  • $callback: Элемент типа callable — обработчик что будет вызван для обработки данной операции. Например:
    • ['\Drupal\MyModule\Batch', 'methodName']
    • [$this, 'methodName'] или [get_class($this), 'methodName'] или [self::class, 'methodName']
    • ['function_name']
  • $arguments: Массив данных, который будет передан обработчику.

На каждую операцию нужно делать собственный вызов. Операций может быть сколько угодно, а также, каждая операция может иметь свой собственный обработчик.

Пример:

$data_to_process = [
  ['foo', 'bar'],
  ['baz'],
];

foreach ($data_to_process as $data) {
  $batch->addOperation([$this, 'processData'], $data);
}

setFinishCallback()

Метод setFinishCallback() позволяет указать функцию обратного вызова, которая будет вызвана после успешного завершения всех операций.

Пример:

$batch->setFinishCallback([$this, 'finished']);

toArray()

Метод toArray() преобразовывает все настройки, заданные при помощи методов BatchBuilder в массив.

Batch в Drupal изначально формировался при помощи массивов и вся основная логика ожидает массив. Начиная с Drupal 8.6.0 был добавлен данный объект, упрощающий формирование пакетной обработки. Тем не менее запуск операций по-прежнему базируется на массиве, чтобы не ломать обратную совместимость. Поэтому, подготовленные данные нужно преобразовывать в правильно структурированный массив, чем данный метод и занимается.

Пример:

batch_set($batch->toArray());

Запуск пакетной обработки

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

Запуск производится при помощи двух функций:

  • batch_set(): Принимает структурированный массив пакетной обработки созданный при помощи BatchBuilder или руками, и сохраняет его до запуска.
  • batch_process(): Перенаправляет пользователя на страницу пакетной обработки и запускает её.

В общем случае выглядит это следующим образом:

$data_to_process = [
  ['foo', 'bar'],
  ['baz'],
];

$batch = new BatchBuilder();
$batch
  ->setTitle(new TranslatableMarkup('My batch'))
  ->setInitMessage(new TranslatableMarkup('Prepare operations for processing.'));

foreach ($data_to_process as $data) {
  $batch->addOperation([$this, 'processData'], $data);
}

batch_set($batch->toArray());
batch_process();

В ситуации, когда вы хотите запустить пакетную обработки из формы, вам не нужно вызывать batch_process(), так как это сделает сам Form API, после того как обработка формы корректно завершится.

Ссылки

🌱 Помогите нам сделать документацию лучше!

Вся документация Druki с отрытым исходным кодом. Нашли ошибку или неточность? Создайте pull request.

Редактировать текущий документ Обсудить улучшение

Или узнайте как контрибутить.

🤔 По-прежнему нужна помощь?

Не нашли ответа на свой вопрос? Попросите помощи у сообщества!

Задайте вопрос на GitHub Смотрите другие ресурсы сообщества