Drupal8: QueueWorker плагины для cron

Дубовской Александр
Team lead

В drupal8, в дополнение к известному механизму hook_cron добавились QueueWorker плагины.

Как было раньше:

/**
 * Implements hook_cron().
 */
function my_module_cron() {
  $queue = \Drupal::queue('my_task');
  $end = time() + 30;
  while (time() < $end && ($item = $queue->claimItem())) {

    do_some_job();

    # Удаляем обработанную запись
    $queue->deleteItem($item);
  }
}

 Теперь можно просто создать отдельный плагин, добавляем в наш модуль в /src/Plugin/IterateJobList.php :

 

<?php

namespace Drupal\my_module\Plugin\QueueWorker;

use Drupal\Core\Queue\QueueWorkerBase;

/**
 *
 * @QueueWorker(
 *   id = "my_module_queue",
 *   title = @Translation("Run my job item"),
 *   cron = {"time" = 60}
 * )
 */
class IterateJobList extends QueueWorkerBase  {
  /**
   * Works on a single queue item.
   *
   * @param mixed $data
   *   The data that was passed to
   *   \Drupal\Core\Queue\QueueInterface::createItem() when the item was queued.
   *
   * @throws \Drupal\Core\Queue\RequeueException
   *   Processing is not yet finished. This will allow another process to claim
   *   the item immediately.
   * @throws \Exception
   *   A CreateJobList plugin may throw an exception to indicate there was a
   *   problem. The cron process will log the exception, and leave the item in
   *   the queue to be processed again later.
   * @throws \Drupal\Core\Queue\SuspendQueueException
   *   More specifically, a SuspendQueueException should be thrown when a
   *   CreateJobList plugin is aware that the problem will affect all subsequent
   *   workers of its queue. For example, a callback that makes HTTP requests
   *   may find that the remote server is not responding. The cron process will
   *   behave as with a normal Exception, and in addition will not attempt to
   *   process further items from the current item's queue during the current
   *   cron run.
   *
   * @see \Drupal\Core\Cron::processQueues()
   */
  public function processItem($data) {
     do_some_job();
  }
}

Обратите внимание:

  1. В аннотации к классу мы передаем имя очереди: id = "my_module_queue"
  2. $data - это данные, что раньше в hook_cron мы передавали вручную, что внутри  $queue->claimItem()->data, т.е. вы не получаете весь item как объект, а только массив с данными
  3. По умолчанию при проходе удаление item из очереди происходит автоматом. Т.е. то что раньше вы делали явно через $queue->deleteItem($item), теперь делать не нужно (и нечем). 
  4. Выбросом исключения можно решить участь того что дальше будет - можно не удалять запись из очереди, можно приостановить выполнение всей очереди.

 

Вывод: удобно, проще структурировать cron jobs если их много.