7 system.api.php hook_cron_queue_info()

Declare queues holding items that need to be run periodically.

While there can be only one hook_cron() process running at the same time, there can be any number of processes defined here running. Because of this, long running tasks are much better suited for this API. Items queued in hook_cron() might be processed in the same cron run if there are not many items in the queue, otherwise it might take several requests, which can be run in parallel.

Return value

An associative array where the key is the queue name and the value is again an associative array. Possible keys are:

  • 'worker callback': The name of an implementation of callback_queue_worker().
  • 'time': (optional) How much time Drupal should spend on calling this worker in seconds. Defaults to 15.
  • 'skip on cron': (optional) Set to TRUE to avoid being processed during cron runs (for example, if you want to control all queue execution manually).

See also



Related topics

2 functions implement hook_cron_queue_info()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

aggregator_cron_queue_info in modules/aggregator/aggregator.module
Implements hook_cron_queue_info().
cron_queue_test_cron_queue_info in modules/system/tests/cron_queue_test.module
Implements hook_cron_queue_info().
1 invocation of hook_cron_queue_info()
drupal_cron_run in includes/common.inc
Executes a cron run when called.


modules/system/system.api.php, line 620
Hooks provided by Drupal core and the System module.


function hook_cron_queue_info() {
  $queues['aggregator_feeds'] = array(
    'worker callback' => 'aggregator_refresh',
    'time' => 60,
  return $queues;


Invoked by includes/common.inc

The argument of the worker callback is the data passed to DrupalQueue::createItem(), not to be confused with the queue item returned by the claimItem() method.

I add a cron task,and let all node title add a suffix "abc",just in order to learn how to use these hook.The code can run properly.

 * Implements hook_cron().
function hf_remind_cron(){
$result = db_query('SELECT title,nid FROM {node}');
$queue = DrupalQueue::get('send_emails');
  foreach (
$result as $hf_info) {
 * Implements hook_cron_queue_info().
function hf_remind_cron_queue_info(){
$queues['send_emails'] = array(
'worker callback' => 'hf_sender',
'time' => 120,


$result = db_update('node')
fields(array('title' => $data->title . 'abc'))
condition('nid', $data->nid)

A number of example uses of this hook, including the above, explicitly create the queue in the hook_cron(). It's important to note that this is NOT required to process queues during cron.

If you are pre-populating your queue with items somewhere else in Drupal (for example, on node creation, user saves, or any other arbitrary action), then all that's required to process a queue on cron is to invoke hook_cron_queue_info() using the name of the queue.

Also note that if you're familiar scheduling tasks in hook_cron() using this method, you can use the same logic to return only relevant portions of the array returned in hook_cron_queue_info() to effectively schedule queue processing.

Be aware that after the 'worker callback' function is called, the item will be deleted from the queue whether you want it to be or not.

Yeah, this would ideally allow the worker callback to determine whether or not the item were removed from the queue. Makes this very limiting. Perhaps the worker callback could return TRUE to indicate the item was successfully processed and should be removed and FALSE to indicate the item should be kept in the queue and processing should proceed to the next item.

I'm pretty sure you can throw an exception to leave the item in the queue.

example: throw new Exception('Error processing. Item will remain in the queue.');

You can throw an exception in the worker callback to indicate that the worker has failed, and the item will be left in the queue. However, the SystemQueue (default) implementation of DrupalReliableQueueInterface::claimItem() will ignore items that have already been attempted, basically putting them into a hospital queue (limbo) straight away. Queue UI seems to address failed items by allowing you to remove leases.

Ideally, you'd want to put failed items into a limited retry queue with a configurable retry count and wait time, and then shunt them off into a hospital queue with a collated failure record.

EDIT: It looks like Drupal automatically clears queue leases on cron runs (see system_cron()) so failed items will keep retrying indefinitely after each cron run.

It seems the only way to check if you've already added an item to a queue is to use your own table to store IDs and queue times for your items. The example hook_cron() code in modules/system/system.api.php shows one way to do this.

Hi, guys, I'm trying to send a couple of emails using hook_cron, but I'm having some troubles, for each row the function foobar send a mail; when the query returns one row, It's no problem, the mail has two parts one part it's a automatically generated google image, and the other part it's a table with some data related with the image. The problem begins when query returns with two or more rows, in the second mail, the image it's the same of the first mail but the table it's filled with correct data. This is the code.

function my_module_cron(){
$query="SELECT * FROM my_table WHERE date(next_date)='".date('Y-m-d')."'";
foreach($result as $data){

function my_module_cron_queue_info(){
"worker callback"=>"foobar",
return $queues;

function foobar($data){

Anyone know what's going wrong?

It should be precised that the time parameter is a limit for another item in the same queue to be launched after at least the first one as been launched and completed ...

So if you put 10 and your item take 90 second to complete it will complete

It mentions above that if you process your queue with hook_cron_queue_info, the queue item will be deleted after processing, regardless of success or failure. To get around this one can re-add the item to the queue at the end of your callback. But I am observing my entire queue being deleted, even when there is still one unprocessed item left in the queue. Anybody else seen this?

As jacobischwartz mentioned you should put them in another limited "retry" queue. To process items again.