- Patch #578676 by chx | neclimdul, Crell, Dave Reid: introduce a queue for cron.

merge-requests/26/head
Dries Buytaert 2009-09-25 15:20:12 +00:00
parent 92278086bb
commit 762be09fa9
4 changed files with 73 additions and 7 deletions

View File

@ -3837,6 +3837,11 @@ function drupal_cron_run() {
// Fetch the cron semaphore
$semaphore = variable_get('cron_semaphore', FALSE);
$return = FALSE;
// Grab the defined cron queues.
$queues = module_invoke_all('cron_queue_info');
drupal_alter('cron_queue_info', $queues);
if ($semaphore) {
if (REQUEST_TIME - $semaphore > 3600) {
@ -3853,6 +3858,11 @@ function drupal_cron_run() {
}
}
else {
// Make sure every queue exists. There is no harm in trying to recreate an
// existing queue.
foreach ($queues as $queue_name => $info) {
DrupalQueue::get($queue_name)->createQueue();
}
// Register shutdown callback
register_shutdown_function('drupal_cron_cleanup');
@ -3870,8 +3880,19 @@ function drupal_cron_run() {
variable_del('cron_semaphore');
// Return TRUE so other functions can check if it did run successfully
return TRUE;
$return = TRUE;
}
foreach ($queues as $queue_name => $info) {
$function = $info['worker callback'];
$end = time() + (isset($info['time']) ? $info['time'] : 15);
$queue = DrupalQueue::get($queue_name);
while (time() < $end && ($item = $queue->claimItem())) {
$function($item->data);
$queue->deleteItem($item);
}
}
return $return;
}
/**

View File

@ -306,18 +306,30 @@ function aggregator_permission() {
/**
* Implement hook_cron().
*
* Checks news feeds for updates once their refresh interval has elapsed.
* Queues news feeds for updates once their refresh interval has elapsed.
*/
function aggregator_cron() {
$result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh != :never', array(
':time' => REQUEST_TIME,
':never' => AGGREGATOR_CLEAR_NEVER
));
$queue = DrupalQueue::get('aggregator_feeds');
foreach ($result as $feed) {
aggregator_refresh($feed);
$queue->createItem($feed);
}
}
/**
* Implement hook_cron_queue_info().
*/
function aggregator_cron_queue_info() {
$queues['aggregator_feeds'] = array(
'worker callback' => 'aggregator_refresh',
'time' => 60,
);
return $queues;
}
/**
* Implement hook_block_info().
*/

View File

@ -128,7 +128,8 @@ class AggregatorTestCase extends DrupalWebTestCase {
*/
function updateAndRemove($feed, $expected_count) {
$this->updateFeedItems($feed, $expected_count);
$this->assertText('There is new syndicated content from');
$count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
$this->assertTrue($count);
$this->removeFeedItems($feed);
$count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
$this->assertTrue($count == 0);

View File

@ -124,19 +124,51 @@ function hook_entity_info_alter(&$entity_info) {
* intervals can implement hook_cron(). The engine will then call the hook
* at the appropriate intervals defined by the administrator. This interface
* is particularly handy to implement timers or to automate certain tasks.
* Database maintenance, recalculation of settings or parameters, and
* automatic mailings are good candidates for cron tasks.
* Database maintenance, recalculation of settings or parameters are good
* candidates for cron tasks.
* Long running tasks should use the queue API, define one or more queues with
* hook_cron_queue_info() and put items in the queue instead of running them in
* hook_cron(). Examples of jobs that are good candidates for hook_cron_queue_info
* include automated mailing, retrieving remote data, and intensive file tasks.
*
* This hook will only be called if cron.php is run (e.g. by crontab).
*/
function hook_cron() {
$result = db_query('SELECT * FROM {site} WHERE checked = 0 OR checked + refresh < :time', array(':time' => REQUEST_TIME));
$queue = DrupalQueue::get('aggregator_feeds');
foreach ($result as $site) {
cloud_update($site);
$queue->createItem($site);
}
}
/**
* 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
* 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 the function to call. It will be called
* with one argument, the $item from createItem called
* in hook_cron.
* 'time' How much time Drupal should spend on calling this
* worker in seconds. Optional, defaults to 15.
*/
function hook_cron_queue_info() {
$queues['aggregator_feeds'] = array(
'worker callback' => 'aggregator_refresh',
'time' => 15,
);
return $queues;
}
/**
* Allows modules to declare their own Forms API element types and specify their
* default values.