mirror of
https://github.com/moodle/moodle.git
synced 2025-08-07 09:56:38 +02:00
MDL-55231 core_course: Partial course cache rebuild
This commit is contained in:
parent
e5894c0455
commit
9a900492bc
15 changed files with 406 additions and 177 deletions
|
@ -221,8 +221,16 @@ $definitions = array(
|
|||
'simplekeys' => true,
|
||||
'ttl' => 3600,
|
||||
),
|
||||
// Accumulated information about course modules and sections used to print course view page (user-independed).
|
||||
// Used in function get_fast_modinfo(), reset in function rebuild_course_cache().
|
||||
// Accumulated information about course modules and sections used to print course view page (user-independent).
|
||||
// Used in functions:
|
||||
// - course_modinfo::build_course_section_cache()
|
||||
// - course_modinfo::inner_build_course_cache()
|
||||
// - get_array_of_activities()
|
||||
// Reset/update in functions:
|
||||
// - rebuild_course_cache()
|
||||
// - course_purge_module_cache()
|
||||
// - course_purge_section_cache()
|
||||
// - remove_course_contents().
|
||||
'coursemodinfo' => array(
|
||||
'mode' => cache_store::MODE_APPLICATION,
|
||||
'simplekeys' => true,
|
||||
|
|
|
@ -514,7 +514,7 @@ class course_modinfo {
|
|||
' does not have context. Rebuilding cache for course '. $course->id);
|
||||
// Re-request the course record from DB as well, don't use get_course() here.
|
||||
$course = $DB->get_record('course', array('id' => $course->id), '*', MUST_EXIST);
|
||||
$coursemodinfo = self::build_course_cache($course);
|
||||
$coursemodinfo = self::build_course_cache($course, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -553,6 +553,7 @@ class course_modinfo {
|
|||
$this->instances[$cm->modname] = array();
|
||||
}
|
||||
$this->instances[$cm->modname][$cm->instance] = $cm;
|
||||
ksort($this->instances[$cm->modname]);
|
||||
$this->cms[$cm->id] = $cm;
|
||||
|
||||
// Reconstruct sections. This works because modules are stored in order
|
||||
|
@ -562,6 +563,8 @@ class course_modinfo {
|
|||
$this->sections[$cm->sectionnum][] = $cm->id;
|
||||
}
|
||||
|
||||
ksort($this->cms);
|
||||
ksort($this->instances);
|
||||
// Expand section objects
|
||||
$this->sectioninfo = array();
|
||||
foreach ($coursemodinfo->sectioncache as $number => $data) {
|
||||
|
@ -588,23 +591,37 @@ class course_modinfo {
|
|||
* in some other way.)
|
||||
*
|
||||
* @param stdClass $course Course object (must contain fields
|
||||
* @param boolean $usecache use cached section info if exists, use true for partial course rebuild
|
||||
* @return array Information about sections, indexed by section number (not id)
|
||||
*/
|
||||
protected static function build_course_section_cache($course) {
|
||||
protected static function build_course_section_cache(\stdClass $course, bool $usecache = false): array {
|
||||
global $DB;
|
||||
|
||||
// Get section data
|
||||
$sections = $DB->get_records('course_sections', array('course' => $course->id), 'section',
|
||||
'section, id, course, name, summary, summaryformat, sequence, visible, availability');
|
||||
$compressedsections = array();
|
||||
$compressedsections = [];
|
||||
$courseformat = course_get_format($course);
|
||||
|
||||
if ($usecache) {
|
||||
$cachecoursemodinfo = \cache::make('core', 'coursemodinfo');
|
||||
$coursemodinfo = $cachecoursemodinfo->get($course->id);
|
||||
if ($coursemodinfo !== false) {
|
||||
$compressedsections = $coursemodinfo->sectioncache;
|
||||
}
|
||||
}
|
||||
|
||||
$formatoptionsdef = course_get_format($course)->section_format_options();
|
||||
// Remove unnecessary data and add availability
|
||||
foreach ($sections as $number => $section) {
|
||||
$sectioninfocached = isset($compressedsections[$number]);
|
||||
if ($sectioninfocached) {
|
||||
continue;
|
||||
}
|
||||
// Add cached options from course format to $section object
|
||||
foreach ($formatoptionsdef as $key => $option) {
|
||||
if (!empty($option['cache'])) {
|
||||
$formatoptions = course_get_format($course)->get_format_options($section);
|
||||
$formatoptions = $courseformat->get_format_options($section);
|
||||
if (!array_key_exists('cachedefault', $option) || $option['cachedefault'] !== $formatoptions[$key]) {
|
||||
$section->$key = $formatoptions[$key];
|
||||
}
|
||||
|
@ -615,6 +632,7 @@ class course_modinfo {
|
|||
section_info::convert_for_section_cache($compressedsections[$number]);
|
||||
}
|
||||
|
||||
ksort($compressedsections);
|
||||
return $compressedsections;
|
||||
}
|
||||
|
||||
|
@ -652,19 +670,20 @@ class course_modinfo {
|
|||
*
|
||||
* @param stdClass $course object from DB table course. Must have property 'id'
|
||||
* but preferably should have all cached fields.
|
||||
* @param boolean $partialrebuild Indicates it's partial course rebuild or not
|
||||
* @return stdClass object with all cached keys of the course plus fields modinfo and sectioncache.
|
||||
* The same object is stored in MUC
|
||||
* @throws moodle_exception if course is not found (if $course object misses some of the
|
||||
* necessary fields it is re-requested from database)
|
||||
*/
|
||||
public static function build_course_cache($course) {
|
||||
public static function build_course_cache(\stdClass $course, bool $partialrebuild = false): \stdClass {
|
||||
if (empty($course->id)) {
|
||||
throw new coding_exception('Object $course is missing required property \id\'');
|
||||
}
|
||||
|
||||
$lock = self::get_course_cache_lock($course->id);
|
||||
try {
|
||||
return self::inner_build_course_cache($course, $lock);
|
||||
return self::inner_build_course_cache($course, $lock, $partialrebuild);
|
||||
} finally {
|
||||
$lock->release();
|
||||
}
|
||||
|
@ -675,9 +694,11 @@ class course_modinfo {
|
|||
*
|
||||
* @param stdClass $course object from DB table course
|
||||
* @param \core\lock\lock $lock Lock object - not actually used, just there to indicate you have a lock
|
||||
* @param bool $partialrebuild Is partial rebuild or not
|
||||
* @return stdClass Course object that has been stored in MUC
|
||||
*/
|
||||
protected static function inner_build_course_cache($course, \core\lock\lock $lock) {
|
||||
protected static function inner_build_course_cache(\stdClass $course, \core\lock\lock $lock,
|
||||
bool $partialrebuild = false): \stdClass {
|
||||
global $DB, $CFG;
|
||||
require_once("{$CFG->dirroot}/course/lib.php");
|
||||
|
||||
|
@ -693,8 +714,8 @@ class course_modinfo {
|
|||
// This may take time on large courses and it is possible that another user modifies the same course during this process.
|
||||
// Field cacherev stored in both DB and cache will ensure that cached data matches the current course state.
|
||||
$coursemodinfo = new stdClass();
|
||||
$coursemodinfo->modinfo = get_array_of_activities($course->id);
|
||||
$coursemodinfo->sectioncache = self::build_course_section_cache($course);
|
||||
$coursemodinfo->modinfo = get_array_of_activities($course->id, $partialrebuild);
|
||||
$coursemodinfo->sectioncache = self::build_course_section_cache($course, $partialrebuild);
|
||||
foreach (self::$cachedfields as $key) {
|
||||
$coursemodinfo->$key = $course->$key;
|
||||
}
|
||||
|
@ -2415,9 +2436,22 @@ function get_course_and_cm_from_instance($instanceorid, $modulename, $courseorid
|
|||
* @param int $courseid id of course to rebuild, empty means all
|
||||
* @param boolean $clearonly only clear the cache, gets rebuild automatically on the fly.
|
||||
* Recommended to set to true to avoid unnecessary multiple rebuilding.
|
||||
* @param boolean $partialrebuild will not delete the whole cache when it's true.
|
||||
* use course_purge_module_cache() or course_purge_section_cache() must be
|
||||
* called before when partialrebuild is true.
|
||||
* use course_purge_module_cache() to invalidate mod cache.
|
||||
* use course_purge_section_cache() to invalidate section cache.
|
||||
*
|
||||
* @return void
|
||||
* @throws coding_exception
|
||||
*/
|
||||
function rebuild_course_cache($courseid=0, $clearonly=false) {
|
||||
global $COURSE, $SITE, $DB, $CFG;
|
||||
function rebuild_course_cache(int $courseid = 0, bool $clearonly = false, bool $partialrebuild = false): void {
|
||||
global $COURSE, $SITE, $DB;
|
||||
|
||||
if ($courseid == 0 and !empty($partialrebuild)) {
|
||||
$error = 'partialrebuild only works when a valid course id is provided.';
|
||||
throw new coding_exception($error);
|
||||
}
|
||||
|
||||
// Function rebuild_course_cache() can not be called during upgrade unless it's clear only.
|
||||
if (!$clearonly && !upgrade_ensure_not_running(true)) {
|
||||
|
@ -2433,7 +2467,10 @@ function rebuild_course_cache($courseid=0, $clearonly=false) {
|
|||
if (empty($courseid)) {
|
||||
// Clearing caches for all courses.
|
||||
increment_revision_number('course', 'cacherev', '');
|
||||
$cachecoursemodinfo->purge();
|
||||
if (!$partialrebuild) {
|
||||
$cachecoursemodinfo->purge();
|
||||
}
|
||||
// Clear memory static cache.
|
||||
course_modinfo::clear_instance_cache();
|
||||
// Update global values too.
|
||||
$sitecacherev = $DB->get_field('course', 'cacherev', array('id' => SITEID));
|
||||
|
@ -2446,7 +2483,11 @@ function rebuild_course_cache($courseid=0, $clearonly=false) {
|
|||
} else {
|
||||
// Clearing cache for one course, make sure it is deleted from user request cache as well.
|
||||
increment_revision_number('course', 'cacherev', 'id = :id', array('id' => $courseid));
|
||||
$cachecoursemodinfo->delete($courseid);
|
||||
if (!$partialrebuild) {
|
||||
// Purge all course modinfo.
|
||||
$cachecoursemodinfo->delete($courseid);
|
||||
}
|
||||
// Clear memory static cache.
|
||||
course_modinfo::clear_instance_cache($courseid);
|
||||
// Update global values too.
|
||||
if ($courseid == $COURSE->id || $courseid == $SITE->id) {
|
||||
|
@ -2471,10 +2512,13 @@ function rebuild_course_cache($courseid=0, $clearonly=false) {
|
|||
core_php_time_limit::raise(); // this could take a while! MDL-10954
|
||||
}
|
||||
|
||||
$rs = $DB->get_recordset("course", $select,'','id,'.join(',', course_modinfo::$cachedfields));
|
||||
$fields = 'id,' . join(',', course_modinfo::$cachedfields);
|
||||
$sort = '';
|
||||
$rs = $DB->get_recordset("course", $select, $sort, $fields);
|
||||
|
||||
// Rebuild cache for each course.
|
||||
foreach ($rs as $course) {
|
||||
course_modinfo::build_course_cache($course);
|
||||
course_modinfo::build_course_cache($course, $partialrebuild);
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
|
|
|
@ -365,7 +365,7 @@ class modinfolib_test extends advanced_testcase {
|
|||
$this->assertEquals($USER->id, $modinfo->userid);
|
||||
$this->assertEquals(array(0 => array($forum0->cmid, $assign0->cmid),
|
||||
1 => array($forum1->cmid, $assign1->cmid, $page1->cmid), 3 => array($page3->cmid)), $modinfo->sections);
|
||||
$this->assertEquals(array('forum', 'assign', 'page'), array_keys($modinfo->instances));
|
||||
$this->assertEquals(array('assign', 'forum', 'page'), array_keys($modinfo->instances));
|
||||
$this->assertEquals(array($assign0->id, $assign1->id), array_keys($modinfo->instances['assign']));
|
||||
$this->assertEquals(array($forum0->id, $forum1->id), array_keys($modinfo->instances['forum']));
|
||||
$this->assertEquals(array($page1->id, $page3->id), array_keys($modinfo->instances['page']));
|
||||
|
|
|
@ -25,7 +25,8 @@ information provided here is intended especially for developers.
|
|||
* The completion_info function display_help_icon() which returned the 'Your progress' help icon has been deprecated and
|
||||
should no longer be used.
|
||||
* The completion_info function print_help_icon() which has been deprecated since Moodle 2.0 should no longer be used.
|
||||
* @babel/polyfill has been removed in favour of corejs@3
|
||||
* @babel/polyfill has been removed in favour of corejs@3.
|
||||
* A new parameter $partialrebuild has been added to the rebuild_course_cache.
|
||||
* A new parameter $isbulkupdate has been added to the following functions:
|
||||
- grade_category::update()
|
||||
- grade_category::insert()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue