Overslaan en naar de inhoud gaan

Cron queue-ing

Vandaag liep ik tegen het probleem aan dat ik tijdens een cron-opdracht een grote hoeveelheid nodes moest aanmaken. Nu kan je gewoon je memory_limit en je max_execution_time op een belachelijk niveau zetten of je kan gebruik maken van de hook_cron_queue_info. Hiermee kan je opdrachten laten verzamelen en tegelijk laten uitvoeren tijdens de cronjob.

Het werkt als volg

Ten eerste moet je de hook_cron_queue_info aanroepen en daarin je queue definieren. In dit geval definiëren wij de queue queue_import_nodes. Deze krijgt twee waardes mee, de worker callback en de time. De worker callback definieert de functie die uitgevoerd moet worde en bij de_time_ geef je aan wat de maximale doorlooptijd van die functie mag zijn. De functie die je als worker callback hebt aangemaakt kan in feite alles zijn. In dit geval maakt het een node aan, meer niet.

Als laatste ga je de queue vullen. In mijn voorbeeld doe ik dat in de hook_cron maar het mag in feite overal, als de queue maar gevuld wordt. Met $queue_import = DrupalQueue::get(‘queue_import_nodes’); haal ik mijn queue op en met $queue_import->createItem($node_data); vul ik de queue met opdrachten, per node maak je een item die een nieuwe node aanmaakt. De $node_data die je als argument aan createItem ($node_data) meegeeft is ook het argument wat de functie[module]_import_node() als argument verwacht.

Het op deze manier bouwen van een node import i.c.m. de queue ipv gewoon door de array heen itereren en alles in de cron_hook doen levert veel winst op in de vorm van snelheid en stabiliteit. Het importeren van een 50-tal nodes inclusief velden en afbeeldingen duurt op de simpele manier meer dan een minuut, via de queue nog geen 10 seconden.

1
2
3
4
5
6
7
8
9
10
11
12
<?php
/**
 * Implements hook_cron_queue_info().
 */
function module_cron_queue_info() {
  $queues = array();
  $queues['queue_import_nodes'] = array(
    'worker callback' => 'module_import_node',
    'time' => 60,
  );
  return $queues;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
/**
 * Add a new node from an import.
 * @return object $node
 */
function module_import_node($node_data = array()) {
  $node_data = array_merge(array(
    'title' => '[title]',
    'type' => 'nieuws',
    'status' => 1,
    'language' => LANGUAGE_NONE,
    'created' => time(),
  ), $node_data);
 
  $node = new stdClass();
  $node->type = $node_data['type'];
  node_object_prepare($node);
 
  $node->title = $node_data['title'];
  $node->status = $node_data['status'];
  $node->language = $node_data['language'];
 
  $node = node_submit($node);
  $node->created = $node_data['created'];
  node_save($node);
  return $node;
}
1
2
3
4
5
6
7
8
9
10
11
<?php
/**
 * Implements hook_cron().
 */
function module_cron() {
  $nodes = module_get_imported_nodes();
  $queue_import = DrupalQueue::get('queue_import_nodes');
  foreach ($nodes as $node_data) {
    $queue_import->createItem($node_data);
  }
}