Using Batch API to process Drupal Queue jobs

Hot on the heels of Batch API / Search integration, here is a related recipe to interactively run Drupal Queue jobs using Batch API, instead of waiting for cron or another background process to activate them:

  • Set up the batch process. Here we just expose a new menu item that points to a simple function that sets up the batch process with a hard-coded queue name:
<?php
// @file mymodule.module

/**
 * Implementation of hook_menu().
 */
function mymodule_menu() {
 
$items = array();
 
$items['admin/mymodule/queue'] = array(
   
'title' => 'Run queued jobs',
   
'page callback' => 'mymodule_queue',
   
'access arguments' => array('administer site configuration'),
  );
  return
$items;
}

function
mymodule_queue() {
 
$batch = array(
   
'title' => t('Running queued jobs'),
   
'operations' => array(
      array(
'_mymodule_queue_batch', array('my_job_queue')),
    ),
   
'finished' => '_mymodule_queue_finished',
  );
 
batch_set($batch);
 
batch_process('');
  return
'';
}

?>
  • Implement the batch process. This is the core function where we dequeue items from the given queue to process them:
<?php
// @file mymodule.module

function _mymodule_queue_batch($queue_name, &$context) {
 
drupal_queue_include();

 
// Grab the defined cron queues.
 
$queues = module_invoke_all('cron_queue_info');
 
drupal_alter('cron_queue_info', $queues);
  if (!(
$info = $queues[$queue_name])) return;
 
$queue = DrupalQueue::get($queue_name);

 
// Work off queues.
 
if (!isset($context['sandbox']['completed'])) {
   
$context['sandbox']['completed'] = 0;
   
$context['sandbox']['total'] = $queue->numberOfItems();
  }

 
$function = $info['worker callback'];
 
$end = time() + (isset($info['time']) ? $info['time'] : 15);
  while (
time() < $end && ($item = $queue->claimItem())) {
   
$function($item->data);
   
$queue->deleteItem($item);
   
$context['sandbox']['completed']++;
  }

 
// Update Batch API status.
 
$context['finished'] = empty($context['sandbox']['total']) ? 1 : $context['sandbox']['completed'] / $context['sandbox']['total'];
 
$context['message'] = t('Now processing queue !queue...', array('!queue' => $queue_name));
}

function
_mymodule_queue_finished($success, $results, $operations) {
 
drupal_set_message(t('Processed all jobs.'));
}

?>

That's it! The proverbial exercise to the reader is to show a list of queues, allowing the user to choose which one(s) to process, and creating a new batch operation for each selected queue. Enjoy!

Comments

There's a module for that

Or they could just install the Queue UI module. :) http://drupal.org/project/queue_ui

Queue UI is for D7

Thanks for bringing this module to my attention. The code I describe here works with D6.

Well, no reason it can't be

Well, no reason it can't be backported for the D6 drupal_queue module integration. :)