diff --git a/lang/en/cache.php b/lang/en/cache.php index 6c34d4706c4..a8005aee283 100644 --- a/lang/en/cache.php +++ b/lang/en/cache.php @@ -60,6 +60,7 @@ $string['cachedef_plugin_manager'] = 'Plugin info manager'; $string['cachedef_questiondata'] = 'Question definitions'; $string['cachedef_repositories'] = 'Repositories instances data'; $string['cachedef_search_results'] = 'Search results user data'; +$string['cachedef_grade_categories'] = 'Grade category queries'; $string['cachedef_string'] = 'Language string cache'; $string['cachedef_tags'] = 'Tags collections and areas'; $string['cachedef_userselections'] = 'Data used to persist user selections throughout Moodle'; diff --git a/lib/db/caches.php b/lib/db/caches.php index 7f4fc16ae9f..f9b0bd6c7e4 100644 --- a/lib/db/caches.php +++ b/lib/db/caches.php @@ -271,4 +271,9 @@ $definitions = array( 'staticaccelerationsize' => 3 ), + // Grade categories. Stored at request level as invalidation is very aggressive. + 'grade_categories' => array( + 'mode' => cache_store::MODE_REQUEST, + 'simplekeys' => true, + ), ); diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 672fc08f2f4..b5d64185fc8 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once('grade_object.php'); +require_once(__DIR__ . '/grade_object.php'); /** * grade_category is an object mapped to DB table {prefix}grade_categories @@ -188,7 +188,22 @@ class grade_category extends grade_object { * @return grade_category The retrieved grade_category instance or false if none found. */ public static function fetch($params) { - return grade_object::fetch_helper('grade_categories', 'grade_category', $params); + if ($records = self::retrieve_record_set($params)) { + return reset($records); + } + + $record = grade_object::fetch_helper('grade_categories', 'grade_category', $params); + + // We store it as an array to keep a key => result set interface in the cache, grade_object::fetch_helper is + // managing exceptions. We return only the first element though. + $records = false; + if ($record) { + $records = array($record->id => $record); + } + + self::set_record_set($params, $records); + + return $record; } /** @@ -198,7 +213,14 @@ class grade_category extends grade_object { * @return array array of grade_category insatnces or false if none found. */ public static function fetch_all($params) { - return grade_object::fetch_all_helper('grade_categories', 'grade_category', $params); + if ($records = self::retrieve_record_set($params)) { + return $records; + } + + $records = grade_object::fetch_all_helper('grade_categories', 'grade_category', $params); + self::set_record_set($params, $records); + + return $records; } /** @@ -2604,4 +2626,68 @@ class grade_category extends grade_object { return $defaultcoefficients; } + + /** + * Cleans the cache. + * + * We invalidate them all so it can be completely reloaded. + * + * Being conservative here, if there is a new grade_category we purge them, the important part + * is that this is not purged when there are no changes in grade_categories. + * + * @param bool $deleted + * @return void + */ + protected function notify_changed($deleted) { + self::clean_record_set(); + } + + /** + * Generates a unique key per query. + * + * Not unique between grade_object children. self::retrieve_record_set and self::set_record_set will be in charge of + * selecting the appropriate cache. + * + * @param array $params An array of conditions like $fieldname => $fieldvalue + * @return string + */ + protected static function generate_record_set_key($params) { + return sha1(json_encode($params)); + } + + /** + * Tries to retrieve a record set from the cache. + * + * @param array $params The query params + * @return grade_object[]|bool An array of grade_objects or false if not found. + */ + protected static function retrieve_record_set($params) { + $cache = cache::make('core', 'grade_categories'); + return $cache->get(self::generate_record_set_key($params)); + } + + /** + * Sets a result to the records cache, even if there were no results. + * + * @param string $params The query params + * @param grade_object[]|bool $records An array of grade_objects or false if there are no records matching the $key filters + * @return void + */ + protected static function set_record_set($params, $records) { + $cache = cache::make('core', 'grade_categories'); + return $cache->set(self::generate_record_set_key($params), $records); + } + + /** + * Cleans the cache. + * + * Aggressive deletion to be conservative given the gradebook design. + * The key is based on the requested params, not easy nor worth to purge selectively. + * + * @return void + */ + public static function clean_record_set() { + $cache = cache::make('core', 'grade_categories'); + $cache->purge(); + } } diff --git a/version.php b/version.php index 6b690801067..13c48cd6288 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2016031000.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2016031000.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.