<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tlevi</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Tlevi"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Tlevi"/>
	<updated>2026-06-07T20:09:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Talk:PHPUnit&amp;diff=35835</id>
		<title>Talk:PHPUnit</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Talk:PHPUnit&amp;diff=35835"/>
		<updated>2012-10-17T12:44:00Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I actually needed to execute &lt;br /&gt;
&lt;br /&gt;
  pear install -–alldeps pear.phpunit.de/PHPUnit&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
  pear install -–alldeps phpunit/DbUnit&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
+1 same for me - should be changed in article?&lt;br /&gt;
[[User:Tony Levi|Tony Levi]] 20:44, 17 October 2012 (WST)&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=31886</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=31886"/>
		<updated>2012-01-27T15:51:13Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Keys */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290].&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle.&lt;br /&gt;
&lt;br /&gt;
Please visit the discussion thread at http://moodle.org/mod/forum/discuss.php?d=189498.&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
===Suggestions===&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
===The real thing===&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
===Caches===&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Keys===&lt;br /&gt;
Keys identify a particular element within a cache. Key collisions between elements are NOT allowed and will overwrite each other.&lt;br /&gt;
&lt;br /&gt;
Keys are limited to 256 characters. If a longer key is required, use the &#039;md5&#039; option.&lt;br /&gt;
Internally, this packs the full key with data and validates the full key after it is retrieved from cache to stop collisions.&lt;br /&gt;
&lt;br /&gt;
TODO: evaluate removing this limit&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init(); // in setup.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades and the &#039;purge all caches&#039; page.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30227</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30227"/>
		<updated>2011-11-02T05:36:52Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: add discussion link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290].&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle.&lt;br /&gt;
&lt;br /&gt;
Please visit the discussion thread at http://moodle.org/mod/forum/discuss.php?d=189498.&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
===Suggestions===&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
===The real thing===&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
===Caches===&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters and collisions between elements are NOT allowed.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required it is use a hash of the full key as the cache key and store the full key with the value.&lt;br /&gt;
This allows validation of the full key to stop collisions.&lt;br /&gt;
&lt;br /&gt;
It should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init(); // in setup.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades and the &#039;purge all caches&#039; page.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30221</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30221"/>
		<updated>2011-11-02T05:09:03Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Cache interface */ tweak interface info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
===Suggestions===&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
===The real thing===&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
===Caches===&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters and collisions between elements are NOT allowed.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required it is use a hash of the full key as the cache key and store the full key with the value.&lt;br /&gt;
This allows validation of the full key to stop collisions.&lt;br /&gt;
&lt;br /&gt;
It should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init(); // in setup.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades and the &#039;purge all caches&#039; page.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30159</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30159"/>
		<updated>2011-10-31T01:35:43Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Outline */ remove silly persist info, this is gone now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
===Suggestions===&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
===The real thing===&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
===Caches===&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters and collisions between elements are NOT allowed.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required it is use a hash of the full key as the cache key and store the full key with the value.&lt;br /&gt;
This allows validation of the full key to stop collisions.&lt;br /&gt;
&lt;br /&gt;
It should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades etc.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30158</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30158"/>
		<updated>2011-10-31T00:27:44Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Keys */ update+clarify&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
===Suggestions===&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
===The real thing===&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters and collisions between elements are NOT allowed.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required it is use a hash of the full key as the cache key and store the full key with the value.&lt;br /&gt;
This allows validation of the full key to stop collisions.&lt;br /&gt;
&lt;br /&gt;
It should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades etc.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30157</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30157"/>
		<updated>2011-10-31T00:21:18Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Basic Requirements */ headings for separation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
===Suggestions===&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
===The real thing===&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades etc.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30156</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30156"/>
		<updated>2011-10-31T00:19:52Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Basic Requirements */ Update with current statis referring to requirement items&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
# it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
# any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
# code should continue working 100% without caching enabled.&lt;br /&gt;
# each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
# each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
# each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These items have been relaxed or modified somewhat:&lt;br /&gt;
* (Re #1) supports multiple backend types, one instance of each type is permitted&lt;br /&gt;
** a backend implementation is a &#039;method&#039;, methods implement &#039;types&#039;&lt;br /&gt;
** e.g there is a &#039;shmem&#039; cache type, which can be backed by either APC or XCache methods&lt;br /&gt;
* (Re #2) most caches inside Moodle can use this system, some specialized cases may need to be exempted&lt;br /&gt;
* (Re #3) disabling caching is supported, but static cache will remain active in this case for sanity&lt;br /&gt;
* (Re #3) elements may disappear at any time from the cache, except static with no size constraint&lt;br /&gt;
* (Re #4) Fallback is NOT required, but multiple backends are supported&lt;br /&gt;
* (Re #5) callers must provide a unique key for elements, it is their job to form this according to context&lt;br /&gt;
** Hashing if needed should be performed inside cache_methods, and collisions must NOT be visible to callers (check full keys too)&lt;br /&gt;
* (Re #5) key length is a string with fixed maximum length&lt;br /&gt;
** callers could wrap keys+values and store these with using a cache-key that is md5 of the full key&lt;br /&gt;
** it should be possible to implement an optional extra layer (like the multicache) which does this for us&lt;br /&gt;
* (Re #6) each cache (namespace/tag) has one TTL, NOT per-element&lt;br /&gt;
&lt;br /&gt;
These changes minimise overheads in code and performance while permitting the most common cache uses.&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades etc.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30155</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30155"/>
		<updated>2011-10-30T23:29:59Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Cache interface */ update interface definitions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init(); // returns the singleton&lt;br /&gt;
    public function get_cache($tag, array $types = array(&#039;static&#039;), array $options = array());&lt;br /&gt;
    public function purge_all();&lt;br /&gt;
    public function cron();&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The manager must be able to run a cron and purge for each method, as well as perform get/set operations, this necessitates the following interface for cache methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts);&lt;br /&gt;
    public static function purge_all();&lt;br /&gt;
    public static function init(); // self-test and initialisation (e.g a DB connection), returns boolean&lt;br /&gt;
    public static function cron();&lt;br /&gt;
    public static function type();&lt;br /&gt;
&lt;br /&gt;
    public function get($key);&lt;br /&gt;
    public function put($key, $value); // put(key, null) === remove(key)&lt;br /&gt;
    public function remove($key);&lt;br /&gt;
    public function clear();&lt;br /&gt;
&lt;br /&gt;
    public function __get($name);&lt;br /&gt;
    public function __set($name, $value);&lt;br /&gt;
    public function __isset($name);&lt;br /&gt;
    public function __unset($name);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...moodle code outside the cache_manager should never touch the static functions, it is not necessary.&lt;br /&gt;
&lt;br /&gt;
For easy implementation of the magic methods, each cache_method should extend this class instead:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_method_base implements cache_method_intf {&lt;br /&gt;
    public function __get($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name);&lt;br /&gt;
    }&lt;br /&gt;
    public function __set($name, $value) {&lt;br /&gt;
        $this-&amp;gt;put($name, $value);&lt;br /&gt;
    }&lt;br /&gt;
    public function __isset($name) {&lt;br /&gt;
        return $this-&amp;gt;get($name) !== null;&lt;br /&gt;
    }&lt;br /&gt;
    public function __unset($name) {&lt;br /&gt;
        $this-&amp;gt;remove($name);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface allows each method type to run a cron for cleanup purposes and purge_all for upgrades etc.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30154</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30154"/>
		<updated>2011-10-30T23:08:00Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Database */ remove database section, this is gone now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init() // returns singleton manager instance&lt;br /&gt;
    public static function get_cache($tag, array $options = null)&lt;br /&gt;
    public static function register_method($type, $method)&lt;br /&gt;
    public static function purge_all()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the interface that code within moodle will have to a given cache:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_base {&lt;br /&gt;
    abstract public function get($key)&lt;br /&gt;
    abstract public function put($key, $value)&lt;br /&gt;
    abstract public function remove($key) // same as put($key, null)&lt;br /&gt;
    abstract public function cleanup()&lt;br /&gt;
    abstract public function clear()&lt;br /&gt;
    abstract public function size()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
    public function __set($name, $value)&lt;br /&gt;
    public function __unset($name) // same as set($name, null)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...which is used by each cache method and the &amp;quot;multimethod&amp;quot; internal layer.&lt;br /&gt;
&lt;br /&gt;
The cache manager will require extra functions used for housekeeping, so cache methods (plugins) must extend this base:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts)&lt;br /&gt;
    public static function options()&lt;br /&gt;
    public static function init()&lt;br /&gt;
    public static function cron()&lt;br /&gt;
    public static function type()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abstract class cache_method_base extends cache_base implements cache_method_intf {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface would allow each method type to run a cron for cleanup purposes.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30087</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30087"/>
		<updated>2011-10-24T00:36:39Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Cache list */ fix field length&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init() // returns singleton manager instance&lt;br /&gt;
    public static function get_cache($tag, array $options = null)&lt;br /&gt;
    public static function register_method($type, $method)&lt;br /&gt;
    public static function purge_all()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the interface that code within moodle will have to a given cache:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_base {&lt;br /&gt;
    abstract public function get($key)&lt;br /&gt;
    abstract public function put($key, $value)&lt;br /&gt;
    abstract public function remove($key) // same as put($key, null)&lt;br /&gt;
    abstract public function cleanup()&lt;br /&gt;
    abstract public function clear()&lt;br /&gt;
    abstract public function size()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
    public function __set($name, $value)&lt;br /&gt;
    public function __unset($name) // same as set($name, null)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...which is used by each cache method and the &amp;quot;multimethod&amp;quot; internal layer.&lt;br /&gt;
&lt;br /&gt;
The cache manager will require extra functions used for housekeeping, so cache methods (plugins) must extend this base:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts)&lt;br /&gt;
    public static function options()&lt;br /&gt;
    public static function init()&lt;br /&gt;
    public static function cron()&lt;br /&gt;
    public static function type()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abstract class cache_method_base extends cache_base implements cache_method_intf {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface would allow each method type to run a cron for cleanup purposes.&lt;br /&gt;
&lt;br /&gt;
==Database==&lt;br /&gt;
===Cache list===&lt;br /&gt;
There is a database table to store a list of caches with their tags. The cache information is serialised and stored so setup and options can are preserved.&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_caches (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_caches_id_seq&#039;),&lt;br /&gt;
    tag             varchar(255) NOT NULL,&lt;br /&gt;
    timemodified    bigint NOT NULL,&lt;br /&gt;
    cacheobj        text NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_caches_tag_uix ON mdl_caches (tag);&lt;br /&gt;
CREATE INDEX mdl_caches_tim_ix ON mdl_caches (timemodified);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This allows cron to examine each cache and expire entries (e.g memcache, files, etc) as well as other maintenance.&lt;br /&gt;
Currently static-only caches are specially exempt from this table for performance reasons.&lt;br /&gt;
&lt;br /&gt;
TODO: examine if this is possible in a less ugly way.&lt;br /&gt;
&lt;br /&gt;
===DB Cache type===&lt;br /&gt;
The DB cache type would have a table structured like the following:&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_cache_data (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_cachedata_id_seq&#039;),&lt;br /&gt;
    tag             varchar(255) NOT NULL,&lt;br /&gt;
    key             varchar(255) NOT NULL,&lt;br /&gt;
    timeexpire      bigint NOT NULL,&lt;br /&gt;
    value           text&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_cachedata_tagkey_uix ON mdl_cache_data (tag, key);&lt;br /&gt;
CREATE INDEX mdl_cachedata_expire_ix ON mdl_cache_data (timeexpire);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The expire field allows cron to auto-expire entries without looking at each cache alone.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30086</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30086"/>
		<updated>2011-10-24T00:36:21Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* DB Cache type */ fix field length&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init() // returns singleton manager instance&lt;br /&gt;
    public static function get_cache($tag, array $options = null)&lt;br /&gt;
    public static function register_method($type, $method)&lt;br /&gt;
    public static function purge_all()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the interface that code within moodle will have to a given cache:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_base {&lt;br /&gt;
    abstract public function get($key)&lt;br /&gt;
    abstract public function put($key, $value)&lt;br /&gt;
    abstract public function remove($key) // same as put($key, null)&lt;br /&gt;
    abstract public function cleanup()&lt;br /&gt;
    abstract public function clear()&lt;br /&gt;
    abstract public function size()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
    public function __set($name, $value)&lt;br /&gt;
    public function __unset($name) // same as set($name, null)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...which is used by each cache method and the &amp;quot;multimethod&amp;quot; internal layer.&lt;br /&gt;
&lt;br /&gt;
The cache manager will require extra functions used for housekeeping, so cache methods (plugins) must extend this base:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts)&lt;br /&gt;
    public static function options()&lt;br /&gt;
    public static function init()&lt;br /&gt;
    public static function cron()&lt;br /&gt;
    public static function type()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abstract class cache_method_base extends cache_base implements cache_method_intf {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface would allow each method type to run a cron for cleanup purposes.&lt;br /&gt;
&lt;br /&gt;
==Database==&lt;br /&gt;
===Cache list===&lt;br /&gt;
There is a database table to store a list of caches with their tags. The cache information is serialised and stored so setup and options can are preserved.&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_caches (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_caches_id_seq&#039;),&lt;br /&gt;
    tag             varchar(256) NOT NULL,&lt;br /&gt;
    timemodified    bigint NOT NULL,&lt;br /&gt;
    cacheobj        text NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_caches_tag_uix ON mdl_caches (tag);&lt;br /&gt;
CREATE INDEX mdl_caches_tim_ix ON mdl_caches (timemodified);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This allows cron to examine each cache and expire entries (e.g memcache, files, etc) as well as other maintenance.&lt;br /&gt;
Currently static-only caches are specially exempt from this table for performance reasons.&lt;br /&gt;
&lt;br /&gt;
TODO: examine if this is possible in a less ugly way.&lt;br /&gt;
&lt;br /&gt;
===DB Cache type===&lt;br /&gt;
The DB cache type would have a table structured like the following:&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_cache_data (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_cachedata_id_seq&#039;),&lt;br /&gt;
    tag             varchar(255) NOT NULL,&lt;br /&gt;
    key             varchar(255) NOT NULL,&lt;br /&gt;
    timeexpire      bigint NOT NULL,&lt;br /&gt;
    value           text&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_cachedata_tagkey_uix ON mdl_cache_data (tag, key);&lt;br /&gt;
CREATE INDEX mdl_cachedata_expire_ix ON mdl_cache_data (timeexpire);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The expire field allows cron to auto-expire entries without looking at each cache alone.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30085</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30085"/>
		<updated>2011-10-24T00:05:10Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Cache interface */ expand&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init() // returns singleton manager instance&lt;br /&gt;
    public static function get_cache($tag, array $options = null)&lt;br /&gt;
    public static function register_method($type, $method)&lt;br /&gt;
    public static function purge_all()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the interface that code within moodle will have to a given cache:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_base {&lt;br /&gt;
    abstract public function get($key)&lt;br /&gt;
    abstract public function put($key, $value)&lt;br /&gt;
    abstract public function remove($key) // same as put($key, null)&lt;br /&gt;
    abstract public function cleanup()&lt;br /&gt;
    abstract public function clear()&lt;br /&gt;
    abstract public function size()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
    public function __set($name, $value)&lt;br /&gt;
    public function __unset($name) // same as set($name, null)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...which is used by each cache method and the &amp;quot;multimethod&amp;quot; internal layer.&lt;br /&gt;
&lt;br /&gt;
The cache manager will require extra functions used for housekeeping, so cache methods (plugins) must extend this base:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts)&lt;br /&gt;
    public static function options()&lt;br /&gt;
    public static function init()&lt;br /&gt;
    public static function cron()&lt;br /&gt;
    public static function type()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abstract class cache_method_base extends cache_base implements cache_method_intf {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This interface would allow each method type to run a cron for cleanup purposes.&lt;br /&gt;
&lt;br /&gt;
==Database==&lt;br /&gt;
===Cache list===&lt;br /&gt;
There is a database table to store a list of caches with their tags. The cache information is serialised and stored so setup and options can are preserved.&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_caches (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_caches_id_seq&#039;),&lt;br /&gt;
    tag             varchar(256) NOT NULL,&lt;br /&gt;
    timemodified    bigint NOT NULL,&lt;br /&gt;
    cacheobj        text NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_caches_tag_uix ON mdl_caches (tag);&lt;br /&gt;
CREATE INDEX mdl_caches_tim_ix ON mdl_caches (timemodified);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This allows cron to examine each cache and expire entries (e.g memcache, files, etc) as well as other maintenance.&lt;br /&gt;
Currently static-only caches are specially exempt from this table for performance reasons.&lt;br /&gt;
&lt;br /&gt;
TODO: examine if this is possible in a less ugly way.&lt;br /&gt;
&lt;br /&gt;
===DB Cache type===&lt;br /&gt;
The DB cache type would have a table structured like the following:&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_cache_data (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_cachedata_id_seq&#039;),&lt;br /&gt;
    tag             varchar(256) NOT NULL,&lt;br /&gt;
    key             varchar(256) NOT NULL,&lt;br /&gt;
    timeexpire      bigint NOT NULL,&lt;br /&gt;
    value           text&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_cachedata_tagkey_uix ON mdl_cache_data (tag, key);&lt;br /&gt;
CREATE INDEX mdl_cachedata_expire_ix ON mdl_cache_data (timeexpire);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The expire field allows cron to auto-expire entries without looking at each cache alone.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30084</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=30084"/>
		<updated>2011-10-24T00:02:46Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: /* Database */ Add DB information (this makes me realise how ugly the current implementation is...)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init() // returns singleton manager instance&lt;br /&gt;
    public static function get_cache($tag, array $options = null)&lt;br /&gt;
    public static function register_method($type, $method)&lt;br /&gt;
    public static function purge_all()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the interface that code within moodle will have to a given cache:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_base {&lt;br /&gt;
    abstract public function get($key)&lt;br /&gt;
    abstract public function put($key, $value)&lt;br /&gt;
    abstract public function remove($key) // same as put($key, null)&lt;br /&gt;
    abstract public function cleanup()&lt;br /&gt;
    abstract public function clear()&lt;br /&gt;
    abstract public function size()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
    public function __set($name, $value)&lt;br /&gt;
    public function __unset($name) // same as set($name, null)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...which is used by each cache method and the &amp;quot;multimethod&amp;quot; internal layer.&lt;br /&gt;
&lt;br /&gt;
The cache manager will require extra functions used for housekeeping, so cache methods (plugins) must extend this base:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts)&lt;br /&gt;
    public static function options()&lt;br /&gt;
    public static function init()&lt;br /&gt;
    public static function cron()&lt;br /&gt;
    public static function type()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abstract class cache_method_base extends cache_base implements cache_method_intf {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==Database==&lt;br /&gt;
===Cache list===&lt;br /&gt;
There is a database table to store a list of caches with their tags. The cache information is serialised and stored so setup and options can are preserved.&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_caches (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_caches_id_seq&#039;),&lt;br /&gt;
    tag             varchar(256) NOT NULL,&lt;br /&gt;
    timemodified    bigint NOT NULL,&lt;br /&gt;
    cacheobj        text NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_caches_tag_uix ON mdl_caches (tag);&lt;br /&gt;
CREATE INDEX mdl_caches_tim_ix ON mdl_caches (timemodified);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This allows cron to examine each cache and expire entries (e.g memcache, files, etc) as well as other maintenance.&lt;br /&gt;
Currently static-only caches are specially exempt from this table for performance reasons.&lt;br /&gt;
&lt;br /&gt;
TODO: examine if this is possible in a less ugly way.&lt;br /&gt;
&lt;br /&gt;
===DB Cache type===&lt;br /&gt;
The DB cache type would have a table structured like the following:&lt;br /&gt;
&amp;lt;code sql&amp;gt;&lt;br /&gt;
CREATE TABLE mdl_cache_data (&lt;br /&gt;
    id              bigint PRIMARY KEY DEFAULT nextval(&#039;mdl_cachedata_id_seq&#039;),&lt;br /&gt;
    tag             varchar(256) NOT NULL,&lt;br /&gt;
    key             varchar(256) NOT NULL,&lt;br /&gt;
    timeexpire      bigint NOT NULL,&lt;br /&gt;
    value           text&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
CREATE UNIQUE INDEX mdl_cachedata_tagkey_uix ON mdl_cache_data (tag, key);&lt;br /&gt;
CREATE INDEX mdl_cachedata_expire_ix ON mdl_cache_data (timeexpire);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The expire field allows cron to auto-expire entries without looking at each cache alone.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=29388</id>
		<title>Caching system (proposed)</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Caching_system_(proposed)&amp;diff=29388"/>
		<updated>2011-09-11T13:33:07Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: Initial add, some things clearly missing for the moment&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft}}&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This page documents a proposed design for an implementation of [http://tracker.moodle.org/browse/MDL-25290 MDL25290] .&lt;br /&gt;
&lt;br /&gt;
The purpose is to provide a staging area for the design before it is implemented into code, and document the expected functionality.&lt;br /&gt;
&lt;br /&gt;
The caching system should be a general architecture that can support all uses of caching within Moodle&lt;br /&gt;
&lt;br /&gt;
==Basic Requirements==&lt;br /&gt;
Things the caching system should or must do:&lt;br /&gt;
* it should support different backends (static, session, DB, shared memory...).&lt;br /&gt;
* any attempt of caching within Moodle should end using it (and not other solutions).&lt;br /&gt;
* code should continue working 100% without caching enabled.&lt;br /&gt;
* each use should define one fallback of backend to use so, for example, for caching CFG we could use (shared memory, DB) and the 1st one available is picked.&lt;br /&gt;
* each cached element must be hash-based (hash selection will be critical to determine if it&#039;s globsl/per user/whatever).&lt;br /&gt;
* each cached element must have one TTL&lt;br /&gt;
&lt;br /&gt;
(mostly taken from [http://tracker.moodle.org/browse/MDL-25290 MDL25290], thanks Eloy!)&lt;br /&gt;
&lt;br /&gt;
==Outline==&lt;br /&gt;
The caching system shall provide access to a series of different caches, referenced by a &#039;&#039;tag&#039;&#039;.&lt;br /&gt;
Each cache may store many objects stored within which are referenced by a &#039;&#039;key&#039;&#039; and may utilise several backend storage methods.&lt;br /&gt;
Therefore, to refer to a particular cached element requires a (&#039;&#039;tag&#039;&#039;, &#039;&#039;key&#039;&#039;) pair.&lt;br /&gt;
&lt;br /&gt;
Additional options such as default ttl or maximum desired cache size can be passed in an options array when the cache is created.&lt;br /&gt;
These &#039;parameters&#039; are (strong) advisory, and certain backends may ignore or override them where it is necessary.&lt;br /&gt;
&lt;br /&gt;
===Tags===&lt;br /&gt;
Tags are simple strings of length less than 256 characters and it is the responsibility of programmers utilising the cache to invent a suitable and unique tag; it is possible a convention could be developed to assist with this. Tags are usually stored in a persistent manner, such that caches may be maintained and referenced at a later time for example a cron job that cleans up expired entries or another piece of code that wishes to use the same cache without constructing it afresh or being fully aware of the original options used.&lt;br /&gt;
===Keys===&lt;br /&gt;
Similar to tags, keys are also simple strings of length less than 256 characters.&lt;br /&gt;
&lt;br /&gt;
If a longer key is required, it could be possible to, for example, use a hash of the full key as the cache key, and store the full key in the value which allows you to validate that there is no hash collision later.&lt;br /&gt;
&lt;br /&gt;
(Perhaps we could be implemented transparently for length-limited storage methods and save the trouble?)&lt;br /&gt;
&lt;br /&gt;
===Methods===&lt;br /&gt;
A cache &#039;&#039;method&#039;&#039; is a particular backend storage engine, these are categorised into &#039;&#039;types&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
A cache method implements a single type, and each type may only have one active implementation. This means code inside moodle may request storage types such as static, database, sharedmem and doesn&#039;t need to know about all implementations, or which are available. Whichever method is chosen by the server admin (via $CFG) or default will be transparently used for storage.&lt;br /&gt;
&lt;br /&gt;
Methods are implemented as a new plugin type, so they may be added, upgraded etc like any other plugin within moodle. This allows easy customisation and extension as needed. Core should gradually add the most useful methods by default.&lt;br /&gt;
&lt;br /&gt;
===Cache interface===&lt;br /&gt;
Interface to the cache manager from moodle code, which allows to create/access caches and overall maintainance:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class core_cache_manager {&lt;br /&gt;
    public static function init() // returns singleton manager instance&lt;br /&gt;
    public static function get_cache($tag, array $options = null)&lt;br /&gt;
    public static function register_method($type, $method)&lt;br /&gt;
    public static function purge_all()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
}&lt;br /&gt;
$CACHE = core_cache_manager::init();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the interface that code within moodle will have to a given cache:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
abstract class cache_base {&lt;br /&gt;
    abstract public function get($key)&lt;br /&gt;
    abstract public function put($key, $value)&lt;br /&gt;
    abstract public function remove($key) // same as put($key, null)&lt;br /&gt;
    abstract public function cleanup()&lt;br /&gt;
    abstract public function clear()&lt;br /&gt;
    abstract public function size()&lt;br /&gt;
&lt;br /&gt;
    /* Magic methods for convienience */&lt;br /&gt;
    public function __isset($name)&lt;br /&gt;
    public function __get($name)&lt;br /&gt;
    public function __set($name, $value)&lt;br /&gt;
    public function __unset($name) // same as set($name, null)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
...which is used by each cache method and the &amp;quot;multimethod&amp;quot; internal layer.&lt;br /&gt;
&lt;br /&gt;
The cache manager will require extra functions used for housekeeping, so cache methods (plugins) must extend this base:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
interface cache_method_intf {&lt;br /&gt;
    public static function get_cache($tag, array $opts)&lt;br /&gt;
    public static function options()&lt;br /&gt;
    public static function init()&lt;br /&gt;
    public static function cron()&lt;br /&gt;
    public static function type()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abstract class cache_method_base extends cache_base implements cache_method_intf {&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==Database==&lt;br /&gt;
Add information about database structures here.&lt;br /&gt;
&lt;br /&gt;
==Other==&lt;br /&gt;
Things that didn&#039;t fit above.&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Turnitin_errors&amp;diff=29089</id>
		<title>Turnitin errors</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Turnitin_errors&amp;diff=29089"/>
		<updated>2011-08-08T02:48:33Z</updated>

		<summary type="html">&lt;p&gt;Tlevi: Add 228 code I have just seen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a list of the Turnitin Codes, and their descriptions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Success States 1-99 ==&lt;br /&gt;
*1	General Success State, no errors&lt;br /&gt;
*10	FID 1, FCMD 1 – successful, send to login&lt;br /&gt;
*11	FID 1, FCMD 2 – successful, do not send to login	&lt;br /&gt;
*20	FID 2, FCMD 1 – successful, send to login&lt;br /&gt;
*21	FID 2, FCMD 2 – successful, do not sent to login&lt;br /&gt;
*30	FID 3, FCMD 1 – successful, send to login&lt;br /&gt;
*31	FID 3, FCMD 2 – successful, do not send to login&lt;br /&gt;
*40	FID 4, FCMD 1,5 – successful, redirect user to assignment creation/modification page&lt;br /&gt;
*41	FID 4, FCMD 2 – successful&lt;br /&gt;
*42	FID 4, FCMD 3 – successful&lt;br /&gt;
*43	FID 4, FCMD 4 – successful&lt;br /&gt;
*50	FID 5, FCMD 1 – successful, redirect user to submission page&lt;br /&gt;
*51	FID 5, FCMD 2 - successful&lt;br /&gt;
*60 	FID 6, FCMD 1 - successful&lt;br /&gt;
*61 	FID 6, FCMD 2 - successful&lt;br /&gt;
*70 	FID 7, FCMD 1,2 – successful&lt;br /&gt;
*70	FID 12, FCMD 1 – successful, redirect to administrator statistics page&lt;br /&gt;
*71 	FID 8, FCMD 2 - successful&lt;br /&gt;
*72 	FID 10, FCMD 2 - successful&lt;br /&gt;
*73	FID 11, FCMD 2 – successful&lt;br /&gt;
*74 	FID 0 – successful &lt;br /&gt;
*75 	FID 9, FCMD 2 - successful&lt;br /&gt;
&lt;br /&gt;
== Data Errors 100-199 ==&lt;br /&gt;
*100	Primary account ID missing from URL &lt;br /&gt;
*101	No HTTPS - the URL was not transmitted via HTTPS&lt;br /&gt;
*102 	GMT missing from URL&lt;br /&gt;
*103	GMT malformed - the date/time in the URL is bad&lt;br /&gt;
*104	Email missing from URL&lt;br /&gt;
*105	Email address is not between 5-75 characters&lt;br /&gt;
*106	Email address contains whitespace&lt;br /&gt;
*107 	Email address in URL is malformed&lt;br /&gt;
*108	Password in URL contained whitespace&lt;br /&gt;
*109	Diagnostic value in URL is bad&lt;br /&gt;
*110	MD5 missing from URL&lt;br /&gt;
*111	fcmd missing from URL&lt;br /&gt;
*112	User first name missing from URL or incorrect length&lt;br /&gt;
*113	User last name missing from URL or incorrect length&lt;br /&gt;
*114	Class title missing from URL, or not between 5-50 characters&lt;br /&gt;
*115	Password is not between 6-12 characters&lt;br /&gt;
*116 	fid missing from URL, or does not reference existing function&lt;br /&gt;
*117 	User type missing from URL or is not valid&lt;br /&gt;
*118 	encrypt value in URL is bad or missing&lt;br /&gt;
*119 	Paper author’s first name missing or incorrect length&lt;br /&gt;
*120 	Paper author’s last name missing or incorrect length&lt;br /&gt;
*121	Paper title missing – Please make sure to include a paper title before submitting your paper&lt;br /&gt;
*122 	Paper type missing or invalid&lt;br /&gt;
*123 	Assignment title missing or incorrect length&lt;br /&gt;
*124	ObjectID missing&lt;br /&gt;
*125	Password is required for function&lt;br /&gt;
*126	Date start and date due is required for function&lt;br /&gt;
*127	If one unique ID is used, they must all be used&lt;br /&gt;
*128	The class end date parameter is not in the right format.  Please make sure that the format is in YYYMMDD.”&lt;br /&gt;
*140	Undocumented, but appears to occur when assignment title is too long.  Should probably return either 2302 or 123 in this situation.&lt;br /&gt;
&lt;br /&gt;
== Turnitin Database Errors 200-299 ==&lt;br /&gt;
*200	Primary account ID for Turnitin not activated to use the API&lt;br /&gt;
*201	IP address validation range for Turnitin not configured&lt;br /&gt;
*202	Primary account entry not active in Turnitin database &lt;br /&gt;
*203	MD5 key missing from Turnitin database&lt;br /&gt;
*204	Class does not exist in Turnitin database.  Please contact you instructor for further details.&lt;br /&gt;
*205	Database error verifying class&lt;br /&gt;
*206	Assignment does not exist in Turnitin database for this class.  The assignment may have been deleted.&lt;br /&gt;
*207	Database error verifying assignment&lt;br /&gt;
*208	User is not enrolled in class&lt;br /&gt;
*209	Database error verifying user’s enrollment in class&lt;br /&gt;
*210	User password does not match user email&lt;br /&gt;
*211	Database error verifying objectID&lt;br /&gt;
*212 	objectID does not exist for this user&lt;br /&gt;
*213 	objectID does not belong to this user &lt;br /&gt;
*214	Filename does not exist for this paper&lt;br /&gt;
*215	This primary account ID is not authorized to use this product&lt;br /&gt;
*216 	Student limit for this account has been reached.  Cannot join student to this class.&lt;br /&gt;
*217	The product for this account has expired.  Please contact your sales agent to renew the product&lt;br /&gt;
*218	Database Error inserting unique ID into the database&lt;br /&gt;
*219	Unique user id in the database does not match submitted uid&lt;br /&gt;
*220	More than one class exists with this title and unique ids must be used in this case&lt;br /&gt;
*221	More than one assignment exists with this title and unique ids must be used in this case&lt;br /&gt;
*222	User is associated with a different external uid.  If you have another user account with the same email address as the user account you are currently using, that could be the cause of the problem.  Please try modifying the email address for your current user account to a unique email address and try again.&lt;br /&gt;
*223	Cannot verify Blackboard user’s identity within Turnitin.  Missing Blackboard user id&lt;br /&gt;
*224	Could not verify user as primary instructor for this course&lt;br /&gt;
*225	Database error checking if student can view reports&lt;br /&gt;
*226	The class you are trying to update could not be found.  Please check to make sure that the class exists.&lt;br /&gt;
*227 	The class you are trying to update has an assignment which ends after the class end date you have specified.  Please change you class end date or modify the assignment.&lt;br /&gt;
*228 	The assignment with the assignment id that you entered does not belong to the class with the class id you entered.  Please check to make sure that you are not using a duplicate assignment id.&lt;br /&gt;
&lt;br /&gt;
== Inconsistency Errors 300-399 ==&lt;br /&gt;
*300 	Your IP address does not fall within the range of accepted IP addresses as specified by your Turnitin account administrator.  Please check with your Turnitin account administrator if your IP address needs to be added as an accepted IP address.&lt;br /&gt;
*301	Date/time expired – GMT timestamp used in MD5 calculation is off. API calls must have a GMT within 60 	minutes of the current GMT&lt;br /&gt;
*302	MD5 not authenticated - the MD5 in the URL does not match the MD5 calculated&lt;br /&gt;
&lt;br /&gt;
== Function Errors 400-499 ==&lt;br /&gt;
*400	Creating new user failed&lt;br /&gt;
*401	Unauthorized access - user exists, but does not belong to correct primary account ID or sub-account ID, do not execute function&lt;br /&gt;
*402	User is not an instructor, must be an instructor to run this function&lt;br /&gt;
*403	User is not a student, must be a student to run this function&lt;br /&gt;
*404 	FCMD is not valid&lt;br /&gt;
*405	Class title is not unique&lt;br /&gt;
*406	Creating new class failed in fid 2&lt;br /&gt;
*407	Student failed to join or log in to a class in fid 3&lt;br /&gt;
*408 	Attempt to join new user to account failed&lt;br /&gt;
*409 	Function requires POST request&lt;br /&gt;
*410	Function requires GET request&lt;br /&gt;
*411 	Creating/Updating/Deleting assignment failed in fid 4&lt;br /&gt;
*412	Assignment title is not unique&lt;br /&gt;
*413 	Error while trying to save the paper&lt;br /&gt;
*414	Originality report not generated yet in fid 6, fcmd 1&lt;br /&gt;
*415 	Originality score not available yet in fid 6, fcmd 2&lt;br /&gt;
*416	Error checking if submission existed for user&lt;br /&gt;
*417	Error trying to change user password&lt;br /&gt;
*418	Error trying to delete submission&lt;br /&gt;
*419	Could not create a new assignment.  An assignment with this title already exists for this class and 		instructor.  Please change the assignment title.&lt;br /&gt;
*420	Error trying to build up session data for user/class&lt;br /&gt;
*421	Error trying to retrieve paper submission info for assignment&lt;br /&gt;
*422	Updating user information failed&lt;br /&gt;
*423	Updating user information failed because user email was changed to an address that is already associated with an account&lt;br /&gt;
*424	Updating class title failed&lt;br /&gt;
*425	Error trying to sync grades between servers&lt;br /&gt;
*426	Error trying to sync roster between servers&lt;br /&gt;
*427 	Unable to establish web services session with remove webct server&lt;br /&gt;
*428	Unable to create WebCT gradebook column for assignment&lt;br /&gt;
*429	Web services parameters error&lt;br /&gt;
*430	(This is a general webservices error – there could be a number of different messages that come with it)&lt;br /&gt;
*431	Error trying to connect back to the Blackboard web service.&lt;br /&gt;
*432	Students are not allowed to view reports in this assignment&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Paper Submission Errors 1000-1099 ==&lt;br /&gt;
*1000	The due date for this assignment has passed.  Please see your instructor to request a late submission.&lt;br /&gt;
*1001	You may not submit a paper to this assignment until the assignment start date&lt;br /&gt;
*1002You may not submit a paper to this assignment because the Plagiarism Prevention product is unavailable&lt;br /&gt;
*1003You have reached the maximum limit of 10 papers for the InSite demo account&lt;br /&gt;
*1004Paper author’s first name missing or incorrect length in URL&lt;br /&gt;
*1005Paper author’s last name missing or incorrect length in URL&lt;br /&gt;
*1006Paper title missing&lt;br /&gt;
*1007The file you have uploaded is too big (TurnItIn site has a note that file size may not exceed 10.48576Mb)&lt;br /&gt;
*1008No file uploaded!  Please make sure that you have attached the file that you wish to submit before sending the request&lt;br /&gt;
*1009Invalid file type!  Valid file types are MS Word, Acrobat PDF, Postscript, Text, HTML, WordPerfect (WPD) and Rich Text Format.  Please make sure the format of your file is one of the valid file types.&lt;br /&gt;
*1010You must submit more than 100 characters of non-whitespace&lt;br /&gt;
*1011The paper you are tyring to submit is incorrectly formatted.  There seems to be spaces between each letter in your paper.  Please try submitting again or contact our helpdesk if the problem persists.&lt;br /&gt;
*1012Paper length exceeds limits&lt;br /&gt;
*1013You must submit more than 20 words of text&lt;br /&gt;
*1014You must select an enrolled student as the author of this paper&lt;br /&gt;
*1015You have already submitted a paper to this assignment.  Please contact your instructor to request a resubmission&lt;br /&gt;
*1016This student has already submitted a paper to this assignment.  Please delete the original paper before submitting a new one.&lt;br /&gt;
*1017Paper author&#039;s first name missing or incorrect length in URL&lt;br /&gt;
*1018Paper author&#039;s last name missing or incorrect length in URL&lt;br /&gt;
*1019Paper title exceeds maximum of 200 characters&lt;br /&gt;
*1020 This document cannot be accepted because it contains characters from a character set that is not supported.&lt;br /&gt;
*1021	You have already submitted a paper to this assignment.  Please contact your instructor to request a 	resubmission.&lt;br /&gt;
*1022	This student has already submitted a portfolio item to this assignment.  Please delete the original portfolio 	item before submitting a new one.&lt;br /&gt;
*1023	We&#039;re sorry, but we could not read the PDF you submitted.  Please make sure that the file is not password 	protected and contains selectable text rather than scanned images.&lt;br /&gt;
*1024	The paper you are tyring to submit does not meet our cirteria for a legitimate paper.  Please try submitting 	again or contact our helpdesk if the problem persists.&lt;br /&gt;
&lt;br /&gt;
== Assignment Creation Errors 2025-2324 ==&lt;br /&gt;
*2025	The class name must be between 5-200 characters&lt;br /&gt;
*2026 	The class enrollment password must be between 4-12 characters&lt;br /&gt;
*2027	There was an error processing your request&lt;br /&gt;
*2028	The class end date must be within 6 months of the start date&lt;br /&gt;
*2029	The end date for this class must occur on or after today&lt;br /&gt;
*2030	The end date for this class must occur on or after the start date&lt;br /&gt;
*2031	The end date for this class must occur at least 3 months after the start date&lt;br /&gt;
*2032	There was an error updating the class end date&lt;br /&gt;
*2035	There was an error processing your request&lt;br /&gt;
*2036	There was an error processing your request&lt;br /&gt;
*2100	User first name missing from URL&lt;br /&gt;
*2101	User last name missing from URL&lt;br /&gt;
*2102	Email is missing.  Please make sure that your email address has been set&lt;br /&gt;
*2110	We only allow email addressses with 5-75 characters&lt;br /&gt;
*2111	The email address cannot contain white space&lt;br /&gt;
*2112	Please make sure you are entering a valid email address.  The email address you enter can only contain 	letters, numbers, and the symbols _ (underscore), - (dash), . (period), &#039; (apostrophe), and + (plus).”&lt;br /&gt;
*2300	You have entered an invalid date!&lt;br /&gt;
*2301	You must select a rubric set to user with remediation&lt;br /&gt;
*2302 	The assignment title must be between 2-100 characters&lt;br /&gt;
*2303	The assignment must have a point value between 0 and 1000&lt;br /&gt;
*2304	The assignment instructions must be less than 1000 characters&lt;br /&gt;
*2305	The start date for this assignment must occur on or after today&lt;br /&gt;
*2306	The due date for this assignment must occur on or after the start date&lt;br /&gt;
*2307	The due date for this assignment must occur within 6 months of the start date&lt;br /&gt;
*2308	When creating your assignment, the post date must occur on or before the class end date.  The class end 	date in Turnitin is by default set to 6 months from the day the class was created.  The class end date can be 	chaned in the class update area in Turnitin&lt;br /&gt;
*2309	When creating your assignment, please make sure that the post date is on or after the due date of the 	assignment&lt;br /&gt;
*2310	You must specify a point value for this assignment because this class is using distributed grading&lt;br /&gt;
*2314	When modifying your assignment, please make sure that the post date is on or after the due date of the 	assignment&lt;br /&gt;
*2315	There was an error processing your request&lt;br /&gt;
*2316	There was an error processing your request&lt;br /&gt;
*2317	There was an error processing your request&lt;br /&gt;
*2318	You cannot change the search targets because papers have already been submitted to this assignment.  You must create a new assignment if you would like to change the search targets&lt;br /&gt;
*2319	There was an error processing your request&lt;br /&gt;
*2320	There was an error processing your request&lt;br /&gt;
&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Tlevi</name></author>
	</entry>
</feed>