Queue API в Drupal 7

10.01.2013
Drupal 7's Queue API
Автор:

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.

Голосів: 9 Рейтинг: 4.6

Також по темі

1

Інколи виникає необхідність реалізувати правила контролю доступу, які не відповідають жодним критеріям. Наприклад Ви хочете створити дозволи для окремих нод одного типу матеріалу, або потрібно...

3

Для початку кілька слів про бібліотеку. pChart – це набір класів для побудови графіків, діаграм і т.п. в php. 

4

Наша компанія дуже часто використовує модуль Panels при створенні сайтів. Хоча це рішення додає чимало...

5

 Із розвитком соціальних мереж замовники все частіше хочуть інтегрувати сайт з Facebook, Twitter, Google+ і т.д. На одному з проектів, потрібно було, реалізувати кроспостінг у...

Subscribe to our blog updates