summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-09-25 15:20:12 +0000
committerDries Buytaert <dries@buytaert.net>2009-09-25 15:20:12 +0000
commit762be09fa98bf2c36cf45042c475a3bc9348e448 (patch)
tree614bff163539a82848044e96a2a5552b9c201420
parent92278086bb38a7b25272e6705c615fd9b8133f36 (diff)
downloadbrdo-762be09fa98bf2c36cf45042c475a3bc9348e448.tar.gz
brdo-762be09fa98bf2c36cf45042c475a3bc9348e448.tar.bz2
- Patch #578676 by chx | neclimdul, Crell, Dave Reid: introduce a queue for cron.
-rw-r--r--includes/common.inc23
-rw-r--r--modules/aggregator/aggregator.module16
-rw-r--r--modules/aggregator/aggregator.test3
-rw-r--r--modules/system/system.api.php38
4 files changed, 73 insertions, 7 deletions
diff --git a/includes/common.inc b/includes/common.inc
index 9037365ff..06b42e0f9 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -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;
}
/**
diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module
index ce2da3c48..765f877e6 100644
--- a/modules/aggregator/aggregator.module
+++ b/modules/aggregator/aggregator.module
@@ -306,19 +306,31 @@ 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().
*/
function aggregator_block_info() {
diff --git a/modules/aggregator/aggregator.test b/modules/aggregator/aggregator.test
index 16d5e64ca..2439adbbc 100644
--- a/modules/aggregator/aggregator.test
+++ b/modules/aggregator/aggregator.test
@@ -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);
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index 6a79445ac..67a3d3d56 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -124,20 +124,52 @@ 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.
*