Skip to content

Commit

Permalink
MBS-8702: Improve caching
Browse files Browse the repository at this point in the history
  • Loading branch information
sh-csg committed Feb 19, 2024
1 parent c63fdc2 commit ff95cac
Show file tree
Hide file tree
Showing 8 changed files with 467 additions and 40 deletions.
9 changes: 2 additions & 7 deletions classes/autoupdate.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public static function update_from_delete_event(\core\event\base $event): void {
foreach ($placestore->places as $p) {
if ($p->linkedActivity == $data['objectid']) {
$p->linkedActivity = null;
cachemanager::remove_cmid($data['objectid']);
$changed = true;
}
}
Expand All @@ -105,13 +106,7 @@ public static function update_from_delete_event(\core\event\base $event): void {
*/
public static function reset_backlink_cache(\core\event\base $event): void {
if (isset($data['courseid']) && $data['courseid'] > 0) {
$course = $data['courseid'];
$cache = \cache::make('mod_learningmap', 'backlinks');
$modinfo = get_fast_modinfo($course);
$cms = $modinfo->get_cms();
foreach ($cms as $cm) {
$cache->delete($cm->id);
}
cachemanager::reset_backlink_cache($data['courseid']);
}
}
}
106 changes: 106 additions & 0 deletions classes/cachemanager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php
// This file is part of Moodle - https://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.

namespace mod_learningmap;

/**
* Cache manager class for mod_learningmap
*
* @package mod_learningmap
* @copyright 2021-2024, ISB Bayern
* @author Stefan Hanauska <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cachemanager {
/**
* Resets and rebuilds the backlink cache for the whole instance.
*
* @return void
*/
public static function rebuild_backlink_cache(): void {
$cache = \cache::make('mod_learningmap', 'backlinks');
$cache->purge();
self::build_backlink_cache();
}

/**
* Reset the backlink cache for a course (includes rebuilding it).
*
* @param int $courseid The id of the course.
* @return void
*/
public static function reset_backlink_cache(int $courseid): void {
$cache = \cache::make('mod_learningmap', 'backlinks');
$modinfo = get_fast_modinfo($courseid);
$cms = $modinfo->get_cms();
$cache->delete_many(array_keys($cms));
self::build_backlink_cache($courseid);
}

/**
* Builds the backlink cache for a course or for the whole instance (e.g. after purging the cache).
*
* @param int $courseid Id of the course, if 0 the cache will be built for the whole instance.
* @return void
*/
public static function build_backlink_cache(int $courseid = 0) {
global $DB;
$backlinks = [];
$cache = \cache::make('mod_learningmap', 'backlinks');

$conditions = ['backlink' => 1];
if (!empty($courseid)) {
$conditions['course'] = $courseid;
}

$records = $DB->get_records('learningmap', $conditions, '', 'id, placestore, backlink');
foreach ($records as $record) {
$module = get_coursemodule_from_instance('learningmap', $record->id, 0, true);
$placestore = json_decode($record->placestore);
$coursepageurl = course_get_format($module->course)->get_view_url($module->sectionnum);
$coursepageurl->set_anchor('module-' . $module->id);
foreach ($placestore->places as $place) {
$url = !empty($module->showdescription) ?
$coursepageurl->out() :
new \moodle_url('/mod/learningmap/view.php', ['id' => $module->id]);
$backlinks[$place->linkedActivity][$module->id] = [
'url' => $url,
'name' => $module->name,
'cmid' => $module->id,
];
}
}

foreach ($backlinks as $cmid => $backlink) {
$cache->set($cmid, $backlink);
}

if (empty($courseid)) {
$cache->set('fillstate', time());
}
}

/**
* Removes a cmid from the backlink cache (e.g. when the course module was deleted).
*
* @param int $cmid Course module id
* @return void
*/
public static function remove_cmid(int $cmid) {
$cache = \cache::make('mod_learningmap', 'backlinks');
$cache->delete($cmid);
}
}
53 changes: 53 additions & 0 deletions classes/task/fill_backlink_cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace mod_learningmap\task;
use mod_learningmap\cachemanager;

/**
* Task to fill backlink cache.
*
* @package mod_learningmap
* @copyright 2021-2024, ISB Bayern
* @author Stefan Hanauska
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class fill_backlink_cache extends \core\task\scheduled_task {
/**
* Get a descriptive name for this task (shown to admins).
*
* @return string
*/
public function get_name() {
return get_string('fill_backlink_cache_task', 'mod_learningmap');
}

/**
* Fill backlink cache.
*/
public function execute() {
$cache = \cache::make('mod_learningmap', 'backlinks');

$fillstate = $cache->get('fillstate');

// If the cache is filled within the last 24 hours, do nothing.
if (!empty($fillstate) && $fillstate < time() - 60 * 60 * 24) {
return;
}

cachemanager::build_backlink_cache();
}
}
39 changes: 39 additions & 0 deletions db/tasks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Scheduled task definitions for mod_learningmap
*
* @package mod_learningmap
* @copyright 2021-2024, ISB Bayern
* @author Stefan Hanauska
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

$tasks = [
[
'classname' => 'mod_learningmap\task\fill_backlink_cache',
'blocking' => 1,
'minute' => '*/5',
'hour' => '*',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
'faildelay' => 1,
],
];
1 change: 1 addition & 0 deletions lang/en/learningmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
$string['completiontype'] = 'Type of completion';
$string['editorhelp'] = 'How to use the editor';
$string['editplace'] = 'Edit place';
$string['fill_backlink_cache_task'] = 'Fill learningmap backlink cache';
$string['freetype_required'] = 'FreeType extension to GD is required to run mod_learningmap.';
$string['groupmode'] = 'Group mode';
$string['groupmode_help'] = 'When group mode is active, it is sufficient that one member of the group has completed an activity to be able to have the connected places available.';
Expand Down
47 changes: 16 additions & 31 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

use mod_learningmap\cachemanager;

/**
* Array with all features the plugin supports for advanced settings. Might be moved
* to another place when in use somewhere else.
Expand Down Expand Up @@ -330,49 +332,32 @@ function learningmap_reset_userdata($data) {
* @return void
*/
function learningmap_before_http_headers() {
global $PAGE, $DB, $OUTPUT;
global $PAGE, $OUTPUT;

if ($PAGE->context->contextlevel != CONTEXT_MODULE) {
return '';
}

try {
$cache = cache::make('mod_learningmap', 'backlinks');

$cachekey = $PAGE->cm->id;
$key = $cache->get($cachekey);
$modinfo = get_fast_modinfo($PAGE->course);

if (!$key) {
$instances = $modinfo->get_instances_of('learningmap');
if (count($instances) > 0) {
$backlinks = [];
foreach ($instances as $i) {
$record = $DB->get_record('learningmap', ['id' => $i->instance], 'name, placestore, backlink');
if ($record->backlink == 1) {
$placestore = json_decode($record->placestore);
$coursepageurl = course_get_format($PAGE->course->id)->get_view_url($i->sectionnum);
$coursepageurl->set_anchor('module-' . $i->id);
foreach ($placestore->places as $place) {
$url = !empty($i->showdescription) ?
$coursepageurl->out() :
new moodle_url('/mod/learningmap/view.php', ['id' => $i->id]);
$backlinks[$place->linkedActivity][$i->id] = ['url' => $url, 'name' => $record->name, 'cmid' => $i->id];
}
}
}
foreach ($backlinks as $cmid => $backlink) {
$cache->set($cmid, $backlink);
}
} else {
$cache->set($cachekey, []);
$backlinks = $cache->get($cachekey);

if ($backlinks === false) {
// If the cache is not yet filled, fill it for the current course.
if (!$cache->get('fillstate')) {
cachemanager::build_backlink_cache($PAGE->course->id);
}
} else {
$backlinks[$cachekey] = $key;
// Try again to get the backlinks.
$backlinks = $cache->get($cachekey);
}

$backlinktext = '';

if (!empty($backlinks[$PAGE->cm->id])) {
foreach ($backlinks[$PAGE->cm->id] as $backlink) {
if (!empty($backlinks)) {
$modinfo = get_fast_modinfo($PAGE->course);
foreach ($backlinks as $backlink) {
$cminfo = $modinfo->get_cm($backlink['cmid']);
if ($cminfo->available != 0 && $cminfo->uservisible) {
$backlinktext .= $OUTPUT->render_from_template('learningmap/backtomap', $backlink);
Expand Down
Loading

0 comments on commit ff95cac

Please sign in to comment.