Drupal → Как из drush команды выполнить большую очередь

02.12.2022

Пример выполнения очереди my_queue в drush команде my-module:my-command:

class MyModuleDrushCommands extends DrushCommands {

  /**
   * @command my-module:my-command
   */
  public function myCommand(): void {
    $this->runQueue('my_queue');
  }

  /**
   * Run queue.
   */
  protected function runQueue(string $queue_name, int $ping_interval = 10): void {
    $queue = \Drupal::queue($queue_name);
    $start_timestamp = time();
    $date_formatter = \Drupal::service('date.formatter');

    $this->io()->text("Выполнение очереди $queue_name ({$queue->numberOfItems()})...");
    
    $queue->garbageCollection();

    while ($item = $queue->claimItem()) {
      $queue->releaseItem($item);
    
      $process = Drush::drush(Drush::aliasManager()->getSelf(), 'queue:run', [$queue_name], ['time-limit' => $ping_interval]);
      $process
        ->setTimeout(NULL)
        ->setIdleTimeout(NULL)
        ->start($process->showRealtime());
      $process->wait();
    }

    $this->io()->text("Очередь $queue_name выполнена за {$date_formatter->formatDiff($start_timestamp, time())}");
  }

}

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

Вместо while ($queue->numberOfItems()) используется while ($item = $queue->claimItem()) + $queue->releaseItem($item), потому что numberOfItems() возвращает число всех элементов в очереди, включая тех, что уже в работе (например в параллельном процессе) или отложенных (например уже обработаны, но с ошибкой), что может привести к бесконечному циклу.

Написанное актуально для
Drush 11
Похожие записи

Комментарии

andypost@drupal.org
03.12.2022, 17:04

Жду статью про параллельность исполнения)

Добавить комментарий