diff --git a/classes/task/cache_cleaner.php b/classes/task/cache_cleaner.php new file mode 100644 index 00000000..9b6693df --- /dev/null +++ b/classes/task/cache_cleaner.php @@ -0,0 +1,151 @@ +. + +/* A sandbox that uses the Jobe server (http://github.com/trampgeek/jobe) to run + * student submissions. + * + * This version doesn't do any authentication; it's assumed the server is + * firewalled to accept connections only from Moodle. + * + * @package qtype_coderunner + * @copyright 2024 Paul McKeown, University of Canterbury + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + + +namespace qtype_coderunner\task; + +defined('MOODLE_INTERNAL') || die(); + +use cache; +use cache_helper; +use cache_store_file; +use cache_definition; + +global $CFG; + +/** + * Task for purging old Coderunner cach entries + */ +class cache_cleaner extends \core\task\scheduled_task { + const MAX_AGE = 10; // 7 * 24 * 60 * 6; // Seven days. + + /** + * Return the task's name as shown in admin screens. + * + * @return string + */ + public function get_name() { + return ('Purge Old Coderunner Cache Entries'); // A get_string('purgeoldcacheentries', 'qtype_coderunner');. + } + + /** + * Execute the task. + */ + public function execute() { + + $configerer = \cache_config::instance(); + $defs = $configerer->get_definitions(); + foreach ($defs as $id => $def) { + if ($def['component'] == 'qtype_coderunner' && $def['area'] == 'coderunner_grading_cache') { + $definition = cache_definition::load($id, $def); + mtrace('ID for created definition '.$definition->get_id()); + $stores = cache_helper::get_cache_stores($definition); + $ttl = $definition->get_ttl(); + $days = $ttl / 60 / 60 / 24; + mtrace("Time to live (TTL) is $ttl seconds (= $days days)"); + foreach ($stores as $store) { + mtrace("Store is searchable: " . $store->is_searchable()); + if ($store->is_searchable()) { + $keys = $store->find_all(); + $originalcount = count($keys); + // Do a get on every key. + // The file cache get method should delete keys that are older than ttl + foreach ($keys as $key) { + $value = $store->get($key); + } + $remainingkeys = $store->find_all(); + $newcount = count($remainingkeys); + mtrace("Did a get on all $originalcount keys."); + mtrace("There are $newcount keys remaining."); + } else { + mtrace("Cache isn't searchable so can find all the keys..."); + } + } + break; // Should be only one definition for Coderunner. + } + } + mtrace("Done for now."); + + // Really needed ??? global $DB;. + // $cache = cache::make('qtype_coderunner', 'coderunner_grading_cache'); + // $keys = $cache->find_all(); + // foreach ($keys as $key) { + // mtrace($key); + // } + + + + //if (! $cache instanceof cachestore_file) { + // echo($cache); + // mtrace('Cache store is not a file cache store - cleanup not needed'); + //} else { + // $reflection = new \ReflectionClass($cache); + // $property = $reflection->getProperty('store'); + // $property->setAccessible(true); + + + + + // // Use reflection to access the private method + // $reflection = new \ReflectionClass($cache); + // $method = $reflection->getMethod('get_store'); + // $method->setAccessible(true); + // // Call the private method + // $store = $method->invoke($cache); + + // $reflection = new \ReflectionClass($store); + // $property = $reflection->getProperty('path'); + // $property->setAccessible(true); + // $path = $property->getValue($store); + + // mtrace("qtype_coderunner coderunner_grading_cache cleanup initiated."); + // mtrace("Cache files are stored in: $path"); + // if ($path) { + // // Scans cache directory. + // $files = new \RecursiveDirectoryIterator($path); + // $iterator = new \RecursiveIteratorIterator($files); + // $deleted = 0; + // $found = 0; + // $now = time(); + // foreach ($iterator as $file) { + // if ($file->isFile()) { + // $found++; + // $mtime = $file->getMTime(); + // if (($now - $mtime) > self::MAX_AGE) { + // if (unlink($file->getPathname())) { + // $deleted++; + // } + // } + // } + // } + // mtrace("Found $found cache files in total."); + // mtrace("Deleted $deleted old cache files."); + + //} + } +} diff --git a/db/caches.php b/db/caches.php index 7d0f403d..1464c4e1 100644 --- a/db/caches.php +++ b/db/caches.php @@ -30,11 +30,12 @@ $definitions = [ 'coderunner_grading_cache' => [ 'mode' => cache_store::MODE_APPLICATION, - 'maxsize' => 50000000, + 'maxsize' => 50000000, // This will be ignored by the standard file cache 'simplekeys' => true, 'simpledata' => false, 'canuselocalstore' => true, 'staticacceleration' => true, + 'ttl' => 60, // 14 * 24 * 60 * 60, // Time to live is two weeks. Change as you see fit and reload cache definitions. 'staticaccelerationsize' => 1000000, ], ]; diff --git a/db/tasks.php b/db/tasks.php new file mode 100644 index 00000000..d7387f35 --- /dev/null +++ b/db/tasks.php @@ -0,0 +1,40 @@ +. + +/** + * Defines cache used to store results of quiz attempt steps. + * If a jobe submission is cached we don't need to call jobe again + * as the result will be known :) + * + * @package qtype + * @subpackage coderunner + * @copyright 2024 Paul McKeown, University of Canterbury + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$tasks = [ + [ + 'classname' => 'qtype_coderunner\task\cache_cleaner', + 'blocking' => 0, + 'minute' => 'R', // Random minute. + 'hour' => '1', + 'day' => '*', + 'month' => '*', + 'dayofweek' => '6', // 6=Saturday. + ], +]; diff --git a/version.php b/version.php index 3e80bc68..ba6ff99c 100644 --- a/version.php +++ b/version.php @@ -22,12 +22,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024090600; +$plugin->version = 2024112400; $plugin->requires = 2022041900; $plugin->cron = 0; $plugin->component = 'qtype_coderunner'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '5.4.1'; +$plugin->release = '5.4.1.1'; $plugin->dependencies = [ 'qbehaviour_adaptive_adapted_for_coderunner' => 2024041800,