Категории
(264)
(73)
(42)
SEO
(25)

Queue API в Drupal 7

10.01.2013
Автор:

Queue API — специальный функционал в Drupal, который позволяет формировать на сайте очередь из трудоемких операций, а также, контролировать их выполнение. В отличии от Batch API, Queue API полностью автоматизирует жизнь вашего сайта.

Queue API использует так называемую атомарную операцию (это такие операции, которые выполняются либо как единое целое, либо не выполняются вовсе).

Представим себе следующий сценарий:

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

Тут то нам и пригодится Queue API. С помощью данного инструмента, мы сможем настроить сервер так, чтобы обработка заказов выполнялась в  ночное время, именно тогда, когда пользователей на сайте почти нет, и ресурса сервера, где расположен наш интернет-магазин будет вполне достаточно для обработки и закачки всех заказов. В результате мы получаем сайт с автоматизированной (и оптимизированной(!!!)) системой формирования и отправки отчетов.

Перво наперво, нам нужно "сформировать очередь", то есть составить список операций, выполняемых нашей Queue. Для этого нужно написать функцию, которая будет все это формировать при запуске крона. Крон мы будем использовать, поскольку исполнение запроса в БД - операция по ресурсам малозатратная. В коде я буду вести простую обработку материалов, и буду выбирать материалы старше 1 недели, а на Queue операции буду менять дату обновления материала на текущею.

В примере вы видите использование hook_cronapi, который будет доступен после установки модуля elysia_cron. Здесь я выбираю все материалы сайта, и записываю каждые 20 материалов в очередь для Queue. При этом заметьте: модуль Elysia cron по дефолту будет запускать операции каждый час, эту опцию можно убрать в настройках модуля.

Сам хук:

/**
 * Implements hook_cronapi().
 */
function internetdevels_queue_cronapi($op, $job = NULL) { 
  $items = array(); 
  $items['internetdevels_queue_main'] = array( 
    'description' => 'Send nid to Queue', 
    'rule' => '0 23 * * *', 
    'arguments' => array(20), 
    'callback' => 'internetdevels_queue_select_content', 
  ); 
  return $items; 
}

Функция выполнения крона:

/**
 * Cron function.
 */
function internetdevels_queue_select_content($count) {
  static $start;
  if (empty($start)) {
    $start = 0;
  }
  $nodes = array();
  // Choosing nodes older than 1 week.
  $query = db_select('node', 'n')
    ->condition('n.changed', REQUEST_TIME - ((3600 * 24) * 7), '<')
    ->fields('n', array('nid'))
    ->range($start, $count)
    ->orderBy('n.changed', 'ASC')
    ->execute();
  while ($value = $query->fetchAssoc()) {
    $nodes[] = $value['nid'];
  }
  // If we have such material then send the nodes to the Queue.
  if (count($nodes) !== 0) {
    $start += $count;
    $queue = DrupalQueue::get('internetdevels_main_queue');
    // Return number of queues.
    $count = $queue->numberOfItems();
    $queue->createQueue();
    // Sending array with nodes.
    $queue->createItem($nodes);
    // Set the interval 5 minutes.
    $queue->claimItem($start + (60 * 5));
    internetdevels_queue_select_content($count);
  }
  else {
    return;
  }
}

Материалы мы выбрали, в очередь Queue их записали. Теперь нам нужно настроить обработку очереди, за это отвечает hook_cron_queue_info.

Пример реализации этого хука смотрите ниже:

/**
 * Implements hook_cron_queue_info().
 */
function internetdevels_queue_cron_queue_info() {
  $queues = array();
  $queues['internetdevels_main_queue'] = array(
    // Queue worker function.
    'worker callback' => 'internetdevels_queue_function',
    // The function will be work 10 seconds.
    'time' => 10,
  );
  return $queues;
}

Также давайте рассмотрим функцию, которая выполняет операцию Queue.

/**
 * Queue function.
 */
function internetdevels_queue_function($data) {
  if (!empty($data)) {
    foreach ($data as $key => $value) {
      // Choosing nodes.
      $query = db_select('node', 'n')
        ->condition('n.nid', $value)
        ->condition('n.changed', REQUEST_TIME - ((3600 * 24) * 7), '<')
        ->fields('n', array('nid'))
        ->execute();
      while ($node = $query->fetchAssoc()) {
        // Making something important here with node...
      }
    }
  }
} 

Работая с данным функционалом, метод для удаление очереди следует особо "взять на заметку". Чтобы удалить очередь нужно написать всего лишь 2 строчки:

$queue = DrupalQueue::get('internetdevels_main_queue');
$queue->deleteQueue();

В итоге всех стараний мы имеем готовый функционал обновления материалов с помощью операций Queue API.

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

Ко всему этому, существует модуль, который представляет визуальный интерфейс Queue. Модуль Queue UI избавляет нас от неудобства постоянного просмотра базы данных, и это обстоятельство делает работу с Queue  еще более приятной.

Стоит обратить внимание и на то, что в выполнении операций принимает участие системный крон под названием system_cron. Если операция Queue была завершена успешно (вложилась в часовые рамки), тогда она удалится из списка при первом же запуске крона.

В этом документе Вы можете увидеть сравнительную характеристику Batch API и Queue API.

1 vote, Rating: 5

Также по теме

1

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

2

В моей предыдущей статье рассматривались возможности профайлера PHP кода ...

3

В наши дни все знают о таких интернет-магазинах как eBay, Amazon и.т.д. Но мало...

4

Не все знают, что модуль Views предоставляет довольно обширный ...

5

В продолжение двух предыдущих статьей (тыцьтыць) о профайлерах и, в...

Need a quote? Let's discuss the project!

Are you looking for someone to help you with your Drupal Web Development needs? Let’s get in touch and discuss the requirements of your project. We would love to hear from you.

Join to peoples who already subscribe