Skip to content

Commit

Permalink
MDL-52346 caching: Allow localstorage as a cache option.
Browse files Browse the repository at this point in the history
We display a notification on screen during configuration telling
the administrator if it's safe to map this store to a local storage
cache or not.
  • Loading branch information
mr-russ committed Feb 25, 2016
1 parent 83a9510 commit 4350192
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 6 deletions.
5 changes: 3 additions & 2 deletions cache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ A definition:
'invalidationevents' => array( // Optional
'contextmarkeddirty'
),
'canuselocalstore' => false // Optional
'sharingoptions' => null // Optional
'defaultsharing' => null // Optional
)
Expand Down Expand Up @@ -151,7 +152,7 @@ The following optional settings can also be defined:
* invalidationevents - An array of events that should trigger this cache to invalidate.
* sharingoptions - The sum of the possible sharing options that are applicable to the definition. An advanced setting.
* defaultsharing - The default sharing option to use. It's highly recommended that you don't set this unless there is a very specific reason not to use the system default.

* canuselocalstore - The default is to required a shared cache location for all nodes in a multi webserver environment. If the cache uses revisions and never updates key data, administrators can use a local storage cache for this cache.
It's important to note that internally the definition is also aware of the component. This is picked up when the definition is read, based upon the location of the caches.php file.

The staticacceleration option.
Expand Down Expand Up @@ -269,4 +270,4 @@ There are a couple of considerations to using this method:

Please be aware that if you are using Memcache or Memcached it is recommended to use dedicated Memcached servers.
When caches get purged the memcached servers you have configured get purged, any data stored within them whether it belongs to Moodle or not will be removed.
If you are using Memcached for sessions as well as caching/testing and caches get purged your sessions will be removed prematurely and users will be need to start again.
If you are using Memcached for sessions as well as caching/testing and caches get purged your sessions will be removed prematurely and users will be need to start again.
24 changes: 24 additions & 0 deletions cache/classes/definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@
* + defaultsharing
* [int] The default sharing option to use. It's highly recommended that you don't set this unless there is a very
* specific reason not to use the system default.
* + canuselocalstore
* [bool] The cache is able to safely run with multiple copies on different webservers without any need for administrator
* intervention to ensure that data stays in sync across nodes. This is usually managed by a revision
* system as seen in modinfo cache or language cache. Requiring purge on upgrade is not sufficient as
* it requires administrator intervention on each node to make it work.
*
* For examples take a look at lib/db/caches.php
*
Expand Down Expand Up @@ -308,6 +313,11 @@ class cache_definition {
*/
protected $sharingoptions;

/**
* Whether this cache supports local storages.
* @var bool
*/
protected $canuselocalstore = false;
/**
* The selected sharing option.
* @var int One of self::SHARING_*
Expand Down Expand Up @@ -367,6 +377,7 @@ public static function load($id, array $definition, $unused = null) {
$sharingoptions = self::SHARING_DEFAULT;
$selectedsharingoption = self::SHARING_DEFAULT;
$userinputsharingkey = '';
$canuselocalstore = false;

if (array_key_exists('simplekeys', $definition)) {
$simplekeys = (bool)$definition['simplekeys'];
Expand Down Expand Up @@ -453,6 +464,9 @@ public static function load($id, array $definition, $unused = null) {
$selectedsharingoption = self::SHARING_ALL;
}
}
if (array_key_exists('canuselocalstore', $definition)) {
$canuselocalstore = (bool)$definition['canuselocalstore'];
}

if (array_key_exists('userinputsharingkey', $definition) && !empty($definition['userinputsharingkey'])) {
$userinputsharingkey = (string)$definition['userinputsharingkey'];
Expand Down Expand Up @@ -529,6 +543,7 @@ public static function load($id, array $definition, $unused = null) {
$cachedefinition->sharingoptions = $sharingoptions;
$cachedefinition->selectedsharingoption = $selectedsharingoption;
$cachedefinition->userinputsharingkey = $userinputsharingkey;
$cachedefinition->canuselocalstore = $canuselocalstore;

return $cachedefinition;
}
Expand Down Expand Up @@ -732,6 +747,15 @@ public function require_locking_write() {
return $this->requirelockingwrite;
}

/**
* Returns true if this definition allows local storage to be used for caching.
* @since Moodle 3.1.0
* @return bool
*/
public function can_use_localstore() {
return $this->canuselocalstore;
}

/**
* Returns true if this definition requires a searchable cache.
* @since Moodle 2.4.4
Expand Down
10 changes: 10 additions & 0 deletions cache/forms.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,23 @@ class cache_definition_mappings_form extends moodleform {
* The definition of the form
*/
protected final function definition() {
global $OUTPUT;

$definition = $this->_customdata['definition'];
$form = $this->_form;

list($component, $area) = explode('/', $definition, 2);
list($currentstores, $storeoptions, $defaults) =
cache_administration_helper::get_definition_store_options($component, $area);

$storedata = cache_administration_helper::get_definition_summaries();
if ($storedata[$definition]['mode'] != cache_store::MODE_REQUEST) {
if (isset($storedata[$definition]['canuselocalstore']) && $storedata[$definition]['canuselocalstore']) {
$form->addElement('html', $OUTPUT->notification(get_string('localstorenotification', 'cache'), 'notifymessage'));
} else {
$form->addElement('html', $OUTPUT->notification(get_string('sharedstorenotification', 'cache'), 'notifymessage'));
}
}
$form->addElement('hidden', 'definition', $definition);
$form->setType('definition', PARAM_SAFEPATH);
$form->addElement('hidden', 'action', 'editdefinitionmapping');
Expand Down
1 change: 1 addition & 0 deletions cache/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ public static function get_definition_summaries() {
'component' => $definition->get_component(),
'area' => $definition->get_area(),
'mappings' => $mappings,
'canuselocalstore' => $definition->can_use_localstore(),
'sharingoptions' => self::get_definition_sharing_options($definition->get_sharing_options(), false),
'selectedsharingoption' => self::get_definition_sharing_options($definition->get_selected_sharing_option(), true),
'userinputsharingkey' => $definition->get_user_input_sharing_key()
Expand Down
2 changes: 2 additions & 0 deletions lang/en/cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
$string['invalidlock'] = 'Invalid lock';
$string['invalidplugin'] = 'Invalid plugin';
$string['invalidstore'] = 'Invalid cache store provided';
$string['localstorenotification'] = 'This cache can be safely mapped to a store that is local to each webserver';
$string['lockdefault'] = 'Default';
$string['locking'] = 'Locking';
$string['locking_help'] = 'Locking is a mechanism that restricts access to cached data to one process at a time to prevent the data from being overwritten. The locking method determines how the lock is acquired and checked.';
Expand Down Expand Up @@ -130,6 +131,7 @@
$string['rescandefinitions'] = 'Rescan definitions';
$string['result'] = 'Result';
$string['set'] = 'Set';
$string['sharedstorenotification'] = 'This cache must be mapped to a store that is shared to all webservers';
$string['sharing'] = 'Sharing';
$string['sharing_all'] = 'Everyone.';
$string['sharing_input'] = 'Custom key (entered below)';
Expand Down
9 changes: 5 additions & 4 deletions lib/db/caches.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@
// Used to store processed lang files.
// The keys used are the revision, lang and component of the string file.
// The static acceleration size has been based upon student access of the site.
// NOTE: this data may be safely stored in local caches on cluster nodes.
'string' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'simpledata' => true,
'staticacceleration' => true,
'staticaccelerationsize' => 30
'staticaccelerationsize' => 30,
'canuselocalstore' => true
),

// Used to store cache of all available translations.
// NOTE: this data may be safely stored in local caches on cluster nodes.
'langmenu' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'simpledata' => true,
'staticacceleration' => true,
'canuselocalstore' => true
),

// Used to store database meta information.
Expand Down Expand Up @@ -91,9 +91,9 @@
// This caches the html purifier cleaned text. This is done because the text is usually cleaned once for every user
// and context combo. Text caching handles caching for the combination, this cache is responsible for caching the
// cleaned text which is shareable.
// NOTE: this data may be safely stored in local caches on cluster nodes.
'htmlpurifier' => array(
'mode' => cache_store::MODE_APPLICATION,
'canuselocalstore' => true
),

// Used to store data from the config + config_plugins table in the database.
Expand Down Expand Up @@ -206,6 +206,7 @@
'coursemodinfo' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'canuselocalstore' => true
),
// This is the session user selections cache.
// It's a special cache that is used to record user selections that should persist for the lifetime of the session.
Expand Down

0 comments on commit 4350192

Please sign in to comment.