=== modified file 'includes/common.inc' --- includes/common.inc 2009-09-18 00:04:21 +0000 +++ includes/common.inc 2009-09-18 02:56:25 +0000 @@ -3838,6 +3838,8 @@ function drupal_cron_run() { // Fetch the cron semaphore $semaphore = variable_get('cron_semaphore', FALSE); + + $return = FALSE; if ($semaphore) { if (REQUEST_TIME - $semaphore > 3600) { @@ -3871,8 +3873,18 @@ 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 (module_implements('cron_worker') as $module) { + $function = $module . '_cron_worker'; + $end = time() + variable_get($function, 15); + $queue = DrupalQueue::get($function); + while (time() < $end && ($item = $queue->claimItem())) { + $function($item->data); + $queue->deleteItem($item); + } + } + return $return; } /** === modified file 'modules/aggregator/aggregator.install' --- modules/aggregator/aggregator.install 2009-09-10 06:38:16 +0000 +++ modules/aggregator/aggregator.install 2009-09-16 03:31:42 +0000 @@ -7,6 +7,13 @@ */ /** + * Implement hook_install(). + */ +function aggregator_install() { + DrupalQueue::get('aggregator_cron_worker')->createQueue(); +} + +/** * Implement hook_uninstall(). */ function aggregator_uninstall() { === modified file 'modules/aggregator/aggregator.module' --- modules/aggregator/aggregator.module 2009-09-18 00:04:21 +0000 +++ modules/aggregator/aggregator.module 2009-09-18 02:56:25 +0000 @@ -306,19 +306,29 @@ 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_cron_worker'); foreach ($result as $feed) { - aggregator_refresh($feed); + $queue->createItem($feed); } } /** + * Implement hook_cron_worker(). + * + * Refresh queued news feeds. + */ +function aggregator_cron_worker($feed) { + aggregator_refresh($feed); +} + +/** * Implement hook_block_info(). */ function aggregator_block_info() { === modified file 'modules/aggregator/aggregator.test' --- modules/aggregator/aggregator.test 2009-09-18 00:12:45 +0000 +++ modules/aggregator/aggregator.test 2009-09-18 02:56:25 +0000 @@ -94,7 +94,7 @@ class AggregatorTestCase extends DrupalW $this->assertResponse(200, t('!url is reachable.', array('!url' => $feed->url))); // Refresh the feed (simulated link click). - $this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid); + drupal_cron_run(); // Ensure we have the right number of items. $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid)); @@ -128,7 +128,8 @@ class AggregatorTestCase extends DrupalW */ 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); @@ -396,7 +397,7 @@ class UpdateFeedItemTestCase extends Agg $this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title']))); $feed = db_query("SELECT * FROM {aggregator_feed} WHERE url = :url", array(':url' => $edit['url']))->fetchObject(); - $this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid); + drupal_cron_run(); $before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); @@ -411,7 +412,7 @@ class UpdateFeedItemTestCase extends Agg 'modified' => 0, )) ->execute(); - $this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid); + drupal_cron_run(); $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); === modified file 'modules/aggregator/tests/aggregator_test.info' --- modules/aggregator/tests/aggregator_test.info 2009-04-02 20:50:37 +0000 +++ modules/aggregator/tests/aggregator_test.info 2009-09-17 16:40:37 +0000 @@ -5,4 +5,4 @@ package = Testing version = VERSION core = 7.x files[] = aggregator_test.module -hidden = TRUE +;hidden = TRUE === modified file 'modules/system/system.api.php' --- modules/system/system.api.php 2009-09-18 00:04:21 +0000 +++ modules/system/system.api.php 2009-09-18 02:56:26 +0000 @@ -124,20 +124,90 @@ function hook_entity_info_alter(&$entity * 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 and hook_cron_worker(). + * Automatic mailings, retrieval of remote data are good examples of what + * should be done in hook_cron_worker() instead. * * 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)); + // Don't forget to replace hook with the module name in the queue name. + $queue = DrupalQueue::get('hook_cron_worker'); foreach ($result as $site) { - cloud_update($site); + $queue->createItem($site); } } /** +<<<<<<< TREE + * Perform long running periodic actions. + * + * While there can be only one hook_cron() process running at the same time, + * there can be any number of hook_cron_worker() processes running. Because of + * this, long running tasks are much better suited for hook_cron_worker. + * + * @param $item + * An item from the queue hook_cron_worker, where hook is replaced by the + * module name, same as in function names. + */ +function hook_cron_worker($item) { + cloud_update($item); +} + +/** + * Rewrite database queries, usually for access control. + * + * Add JOIN and WHERE statements to queries and decide whether the primary_field + * shall be made DISTINCT. For node objects, primary field is always called nid. + * For taxonomy terms, it is tid and for vocabularies it is vid. For comments, + * it is cid. Primary table is the table where the primary object (node, file, + * taxonomy_term_node etc.) is. + * + * You shall return an associative array. Possible keys are 'join', 'where' and + * 'distinct'. The value of 'distinct' shall be 1 if you want that the + * primary_field made DISTINCT. + * + * @param $query + * Query to be rewritten. + * @param $primary_table + * Name or alias of the table which has the primary key field for this query. + * Typical table names would be: {block}, {comment}, {forum}, {node}, + * {menu}, {taxonomy_term_data} or {taxonomy_vocabulary}. However, it is more common for + * $primary_table to contain the usual table alias: b, c, f, n, m, t or v. + * @param $primary_field + * Name of the primary field. + * @param $args + * Array of additional arguments. + * @return + * An array of join statements, where statements, distinct decision. + */ +function hook_db_rewrite_sql($query, $primary_table, $primary_field, $args) { + switch ($primary_field) { + case 'nid': + // this query deals with node objects + $return = array(); + if ($primary_table != 'n') { + $return['join'] = "LEFT JOIN {node} n ON $primary_table.nid = n.nid"; + } + $return['where'] = 'created >' . mktime(0, 0, 0, 1, 1, 2005); + return $return; + break; + case 'tid': + // this query deals with taxonomy objects + break; + case 'vid': + // this query deals with vocabulary objects + break; + } +} + +/** +======= +>>>>>>> MERGE-SOURCE * Allows modules to declare their own Forms API element types and specify their * default values. *