1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Task for updating RSS feeds for rss client block 19 * 20 * @package block_rss_client 21 * @author Farhan Karmali <farhan6318@gmail.com> 22 * @copyright Farhan Karmali 2018 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace block_rss_client\task; 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 /** 31 * Task for updating RSS feeds for rss client block 32 * 33 * @package block_rss_client 34 * @author Farhan Karmali <farhan6318@gmail.com> 35 * @copyright Farhan Karmali 2018 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class refreshfeeds extends \core\task\scheduled_task { 39 40 /** The maximum time in seconds that cron will wait between attempts to retry failing RSS feeds. */ 41 const CLIENT_MAX_SKIPTIME = HOURSECS * 12; 42 43 /** 44 * Name for this task. 45 * 46 * @return string 47 */ 48 public function get_name() { 49 return get_string('refreshfeedstask', 'block_rss_client'); 50 } 51 52 /** 53 * This task goes through all the feeds. If the feed has a skipuntil value 54 * that is less than the current time cron will attempt to retrieve it 55 * with the cache duration set to 0 in order to force the retrieval of 56 * the item and refresh the cache. 57 * 58 * If a feed fails then the skipuntil time of that feed is set to be 59 * later than the next expected task time. The amount of time will 60 * increase each time the fetch fails until the maximum is reached. 61 * 62 * If a feed that has been failing is successfully retrieved it will 63 * go back to being handled as though it had never failed. 64 * 65 * Task should therefore process requests for permanently broken RSS 66 * feeds infrequently, and temporarily unavailable feeds will be tried 67 * less often until they become available again. 68 */ 69 public function execute() { 70 global $CFG, $DB; 71 require_once("{$CFG->libdir}/simplepie/moodle_simplepie.php"); 72 73 // We are going to measure execution times. 74 $starttime = microtime(); 75 $starttimesec = time(); 76 77 // Fetch all site feeds. 78 $rs = $DB->get_recordset('block_rss_client'); 79 $counter = 0; 80 mtrace(''); 81 foreach ($rs as $rec) { 82 mtrace(' ' . $rec->url . ' ', ''); 83 84 // Skip feed if it failed recently. 85 if ($starttimesec < $rec->skipuntil) { 86 mtrace('skipping until ' . userdate($rec->skipuntil)); 87 continue; 88 } 89 90 $feed = $this->fetch_feed($rec->url); 91 92 if ($feed->error()) { 93 // Skip this feed (for an ever-increasing time if it keeps failing). 94 $rec->skiptime = $this->calculate_skiptime($rec->skiptime); 95 $rec->skipuntil = time() + $rec->skiptime; 96 $DB->update_record('block_rss_client', $rec); 97 mtrace("Error: could not load/find the RSS feed - skipping for {$rec->skiptime} seconds."); 98 } else { 99 mtrace ('ok'); 100 // It worked this time, so reset the skiptime. 101 if ($rec->skiptime > 0) { 102 $rec->skiptime = 0; 103 $rec->skipuntil = 0; 104 $DB->update_record('block_rss_client', $rec); 105 } 106 // Only increase the counter when a feed is sucesfully refreshed. 107 $counter ++; 108 } 109 } 110 $rs->close(); 111 112 // Show times. 113 mtrace($counter . ' feeds refreshed (took ' . microtime_diff($starttime, microtime()) . ' seconds)'); 114 } 115 116 /** 117 * Fetch a feed for the specified URL. 118 * 119 * @param string $url The URL to fetch 120 * @return \moodle_simplepie 121 */ 122 protected function fetch_feed(string $url) : \moodle_simplepie { 123 // Fetch the rss feed, using standard simplepie caching so feeds will be renewed only if cache has expired. 124 \core_php_time_limit::raise(60); 125 126 $feed = new \moodle_simplepie(); 127 128 // Set timeout for longer than normal to be agressive at fetching feeds if possible.. 129 $feed->set_timeout(40); 130 $feed->set_cache_duration(0); 131 $feed->set_feed_url($url); 132 $feed->init(); 133 134 return $feed; 135 } 136 137 /** 138 * Calculates a new skip time for a record based on the current skip time. 139 * 140 * @param int $currentskip The current skip time of a record. 141 * @return int The newly calculated skip time. 142 */ 143 protected function calculate_skiptime(int $currentskip) : int { 144 // If the feed has never failed, then the initial skiptime will be 0. We use a default of 5 minutes in this case. 145 // If the feed has previously failed then we double that time. 146 $newskiptime = max(MINSECS * 5, ($currentskip * 2)); 147 148 // Max out at the CLIENT_MAX_SKIPTIME. 149 return min($newskiptime, self::CLIENT_MAX_SKIPTIME); 150 } 151 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body