Index: modules/aggregator/aggregator.install =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.install,v retrieving revision 1.28 diff -u -p -r1.28 aggregator.install --- modules/aggregator/aggregator.install 4 Dec 2009 16:49:45 -0000 1.28 +++ modules/aggregator/aggregator.install 1 Feb 2010 17:06:28 -0000 @@ -143,6 +143,12 @@ function aggregator_schema() { 'default' => 0, 'description' => 'Last time feed was checked for new items, as Unix timestamp.', ), + 'queued' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Time when this feed was queued for refresh, 0 if not queued.', + ), 'link' => array( 'type' => 'varchar', 'length' => 255, @@ -195,6 +201,9 @@ function aggregator_schema() { 'url' => array('url'), 'title' => array('title'), ), + 'indexes' => array( + 'queued' => array('queued'), + ), ); $schema['aggregator_item'] = array( @@ -275,3 +284,16 @@ function aggregator_update_7000() { function aggregator_update_7001() { variable_set('aggregator_teaser_length', variable_get('teaser_length')); } + +/** + * Add queued timestamp. + */ +function aggregator_update_7002() { + db_add_field('aggregator_feed', 'queued', array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Time when this feed was queued for refresh, 0 if not queued.', + )); + db_add_index('aggregator_feed', 'queued', array('queued')); +} \ No newline at end of file Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.434 diff -u -p -r1.434 aggregator.module --- modules/aggregator/aggregator.module 13 Jan 2010 14:35:41 -0000 1.434 +++ modules/aggregator/aggregator.module 1 Feb 2010 17:06:28 -0000 @@ -318,14 +318,26 @@ function aggregator_permission() { * 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( + $result = db_query('SELECT * FROM {aggregator_feed} WHERE queued = 0 AND checked + refresh < :time AND refresh != :never', array( ':time' => REQUEST_TIME, ':never' => AGGREGATOR_CLEAR_NEVER )); $queue = DrupalQueue::get('aggregator_feeds'); foreach ($result as $feed) { - $queue->createItem($feed); + if ($queue->createItem($feed)) { + // Add timestamp to avoid queueing item more than once. + db_update('aggregator_feed') + ->fields(array('queued' => REQUEST_TIME)) + ->condition('fid', $feed->fid) + ->execute(); + } } + + // Remove queued timestamp after 6 hours assuming the update has failed. + db_update('aggregator_feed') + ->fields(array('queued' => 0)) + ->condition('queued', REQUEST_TIME - (3600 * 6), '<') + ->execute(); } /** @@ -614,7 +626,6 @@ function aggregator_refresh($feed) { ->key(array('fid' => $feed->fid)) ->fields(array( 'url' => $feed->url, - 'checked' => REQUEST_TIME, 'link' => empty($feed->link) ? $feed->url : $feed->link, 'description' => empty($feed->description) ? '' : $feed->description, 'image' => empty($feed->image) ? '' : $feed->image, @@ -641,14 +652,15 @@ function aggregator_refresh($feed) { } } else { - db_update('aggregator_feed') - ->fields(array('checked' => REQUEST_TIME)) - ->condition('fid', $feed->fid) - ->execute(); - drupal_set_message(t('There is no new syndicated content from %site.', array('%site' => $feed->title))); } + // Regardless of successful or not, indicate that this feed has been checked. + db_update('aggregator_feed') + ->fields(array('checked' => REQUEST_TIME, 'queued' => 0)) + ->condition('fid', $feed->fid) + ->execute(); + // Expire old feed items. if (function_exists('aggregator_expire')) { aggregator_expire($feed); Index: modules/aggregator/aggregator.test =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.test,v retrieving revision 1.37 diff -u -p -r1.37 aggregator.test --- modules/aggregator/aggregator.test 9 Jan 2010 21:54:00 -0000 1.37 +++ modules/aggregator/aggregator.test 1 Feb 2010 17:06:28 -0000 @@ -638,3 +638,48 @@ class ImportOPMLTestCase extends Aggrega $this->submitImportForm(); } } + +class AggregatorCronTestCase extends AggregatorTestCase { + public static function getInfo() { + return array( + 'name' => 'Update on cron functionality', + 'description' => 'Update feeds on cron.', + 'group' => 'Aggregator' + ); + } + + /** + * Add feeds update them on cron. + */ + public function testCron() { + // Create feed and test basic updating on cron. + global $base_url; + $key = variable_get('cron_key', 'drupal'); + $this->createSampleNodes(); + $feed = $this->createFeed(); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key))); + $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.'); + $this->removeFeedItems($feed); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key))); + $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.'); + + // Test feed locking when queued for update. + $this->removeFeedItems($feed); + db_update('aggregator_feed') + ->condition('fid', $feed->fid) + ->fields(array( + 'queued' => REQUEST_TIME, + )) + ->execute(); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key))); + $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.'); + db_update('aggregator_feed') + ->condition('fid', $feed->fid) + ->fields(array( + 'queued' => 0, + )) + ->execute(); + $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key))); + $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.'); + } +} \ No newline at end of file