Skip to content

Commit

Permalink
Issue #94: Added ability for a datasource to have a null cache key, v…
Browse files Browse the repository at this point in the history
…oiding the caching of the content.

Several methods have been deprecated.
- base::get_content_hash
- base::update_config_hash
  • Loading branch information
jaypha committed Oct 3, 2023
1 parent 3e1edf7 commit dd866fb
Show file tree
Hide file tree
Showing 27 changed files with 506 additions and 119 deletions.
4 changes: 2 additions & 2 deletions backup/moodle2/restore_cms_activity_task.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ class restore_cms_activity_task extends restore_activity_task {
* Define (add) particular settings this activity can have
*/
protected function define_my_settings() {
// No particular settings for this activity
// No particular settings for this activity.
}

/**
* Define (add) particular steps this activity can have
*/
protected function define_my_steps() {
// Choice only has one structure step
// Choice only has one structure step.
$this->add_step(new restore_cms_activity_structure_step('cms_structure', 'cms.xml'));
}

Expand Down
2 changes: 1 addition & 1 deletion classes/customfield/cmsfield_handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@ protected function clear_configuration_cache() {
parent::clear_configuration_cache();
$cmstype = new cms_types($this->get_itemid());
$fields = new fields($cmstype->get_sample_cms());
$fields->update_config_hash();
$fields->update_config_cache_key();
}
}
2 changes: 1 addition & 1 deletion classes/customfield/cmsuserlist_handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,6 @@ protected function clear_configuration_cache() {
parent::clear_configuration_cache();
$cmstype = new cms_types($this->get_itemid());
$userlist = new userlist($cmstype->get_sample_cms());
$userlist->update_config_hash();
$userlist->update_config_cache_key();
}
}
3 changes: 1 addition & 2 deletions classes/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ class helper {
* @param string $url
* @param string $icon
* @param string $alt
* @param string $iconcomponent
* @param string|null $iconcomponent
* @param array $options
*
* @return string
*/
public static function format_icon_link(string $url, string $icon, string $alt,
Expand Down
97 changes: 92 additions & 5 deletions classes/local/datasource/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ abstract class base {
/** @var array List of datasource class names in use. */
protected static $datasourceclasses = [];

/**
* @var bool Set to true if the datasource makes use of caching.
* Override and set to false in any datasource that is not to be cached.
*/
public static $usecache = true;

/**
* Create the list of datasources to be used.
*/
Expand Down Expand Up @@ -207,12 +213,38 @@ public static function is_optional(): bool {
}

/**
* Pulls data from the datasource.
* Constructs the data structure to act as the data source.
*
* @return \stdClass
*/
abstract public function get_data(): \stdClass;

/**
* Constructs the data structure to act as the data source. Uses a cache.
*
* @return \stdClass
* @throws \coding_exception
*/
public function get_cached_data(): \stdClass {
if (!static::$usecache) {
return $this->get_data();
}

$key = $this->get_full_cache_key();

if (is_null($key)) {
return $this->get_data();
}

$cache = \cache::make('mod_cms', 'cms_content_' . self::get_shortname());
$data = $cache->get($key);
if ($data === false) {
$data = $this->get_data();
$cache->set($key, $data);
}
return $data;
}

/**
* Add fields to the CMS instance form.
*
Expand Down Expand Up @@ -313,21 +345,76 @@ public function set_from_import(\stdClass $data) {
/**
* Returns a hash of the content, representing the data stored for the datasource.
*
* @return string
* @deprecated
* @return string|null
* @throws \moodle_exception
*/
abstract public function get_content_hash(): string;
public function get_content_hash(): ?string {
throw new \moodle_exception('This method is deprecated. Use get_instance_cache_key() instead');
}

/**
* Update the config hash.
* Returns the cache key fragment for the instance data.
* If null, then caching should be avoided, both here and for the overall instance.
*
* @return string|null
*/
public function update_config_hash() {
public function get_instance_cache_key(): ?string {
if (!empty($this->cms->get('id'))) {
$this->cms->read();
}
return $this->cms->get_custom_data(self::get_shortname() . 'instancehash') ?? '';
}

/**
* Returns the cache key fragment for the config.
* If null, then caching should be avoided, both here and for the overall instance.
*
* @return string|null
*/
public function get_config_cache_key(): ?string {
$cmstype = $this->cms->get_type();
return $cmstype->get_custom_data(self::get_shortname() . 'confighash') ?? '';
}

/**
* Gets the current cache key used for this datasource for this instance. It concatenates the instance and config keys.
* If either key is null, then this function returns null.
*
* @return string|null
*/
public function get_full_cache_key(): ?string {
if (!static::$usecache) {
return '';
}
$ikey = $this->get_instance_cache_key();
$ckey = $this->get_config_cache_key();
if (is_null($ikey) || is_null($ckey)) {
return null;
}
return $ikey . $ckey;
}

/** Updates the config cache key fragment. */
public function update_config_cache_key() {
// TODO: Switch to revision based hashing?
$hash = hash(lib::HASH_ALGO, serialize($this->get_for_export()));
// The config hash is stored with the CMS type.
$cmstype = $this->cms->get_type();
$cmstype->set_custom_data(self::get_shortname() . 'confighash', $hash);
$cmstype->save();
}

/**
* Update the config hash.
*
* @deprecated
* @throws \moodle_exception
*/
public function update_config_hash() {
throw new \moodle_exception('This method is deprecated. Use update_config_cache_key() instead');
}

/**
* Called when deleting a CMS type.
*/
Expand Down
6 changes: 4 additions & 2 deletions classes/local/datasource/fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public function set_from_import(\stdClass $data) {
}
}
}
$this->update_config_hash();
$this->update_config_cache_key();
}

/**
Expand All @@ -213,8 +213,10 @@ public function set_from_import(\stdClass $data) {
public function update_instance(\stdClass $instancedata, bool $isnewinstance) {
// Save the custom field data.
$this->cfhandler->instance_form_save($instancedata, $isnewinstance);

// Update the instance cache key.
// TODO: Change to use hash of $instancedata?
$hash = hash(lib::HASH_ALGO, serialize($this->get_data()));
// The content hash is stored as a part fo the cms.
$this->cms->set_custom_data('fieldsinstancehash', $hash);
$this->cms->save();
}
Expand Down
9 changes: 5 additions & 4 deletions classes/local/datasource/images.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public function config_on_update($data) {
$this->cms->get('typeid')
);
}
$this->update_config_hash();
$this->update_config_cache_key();
}

/**
Expand Down Expand Up @@ -204,15 +204,16 @@ public function set_from_import(\stdClass $data) {
$fs->create_file_from_string($filerecord, base64_decode($filedata->content));
}
}
$this->update_config_cache_key();
}

/**
* Returns a hash of the content, representing the data stored for the datasource.
* Returns the cache key for the instance data.
*
* @return string
*/
public function get_content_hash(): string {
// There is no instance specific data, so no content hash is needed.
public function get_instance_cache_key(): string {
// There is no instance specific data, so key fragment is constant.
return '';
}

Expand Down
26 changes: 15 additions & 11 deletions classes/local/datasource/roles.php
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public function config_on_update($data) {
];
$cmstype->set_custom_data('roles_config', $config);
$cmstype->save();
$this->update_config_hash();
$this->update_config_cache_key();
}

/**
Expand Down Expand Up @@ -275,16 +275,7 @@ public function set_from_import(\stdClass $data) {
];
$cmstype->set_custom_data('roles_config', $config);
$cmstype->save();
}

/**
* Returns a hash of the content, representing the data stored for the datasource.
*
* @return string
*/
public function get_content_hash(): string {
// Hash is stored in the DB with the cms, so gets returned by cms::get_content_hash().
return '';
$this->update_config_cache_key();
}

/**
Expand Down Expand Up @@ -314,6 +305,19 @@ function($v) {
);
}

/**
* Returns the cache key fragment for the instance data.
* If null, then caching should be avoided, both here and for the overall instance.
*
* @return string|null
*/
public function get_instance_cache_key(): ?string {
if (!empty($this->cms->get('id'))) {
$this->cms->read();
}
return $this->cms->get_custom_data('roles_course_role_cache_rev') ?? '';
}

/**
* Called whenever a role assignment has changed in order to update the datasource cache.
*
Expand Down
15 changes: 4 additions & 11 deletions classes/local/datasource/site.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class site extends base {

/** @var bool Set to false when the datasource doees not cache. */
public static $usecache = false;

/**
* Get the display name.
*
Expand Down Expand Up @@ -57,15 +61,4 @@ public function get_data(): \stdClass {
public static function is_optional(): bool {
return false;
}

/**
* Returns a hash of the content, representing the data stored for the datasource.
*
* @return string
*/
public function get_content_hash(): string {
// There is no instance specific data, so no content hash is needed.
return '';
}

}
17 changes: 4 additions & 13 deletions classes/local/datasource/userlist.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ public function update_instance(\stdClass $instancedata, bool $isnewinstance) {
$this->cms->set_custom_data('userlistinstanceids', $instanceids);
}

// Update hash.
// Update the instance cache key.
// TODO: Change to use $instancedata->data?
$hash = hash(lib::HASH_ALGO, serialize($this->get_data()));
// The content hash is stored as a part fo the cms.
$this->cms->set_custom_data('userlistinstancehash', $hash);
$this->cms->save();
}
Expand Down Expand Up @@ -373,7 +373,7 @@ public function config_on_update($data) {
if (count($categories) === 0) {
$this->cfhandler->create_category('');
}
$this->update_config_hash();
$this->update_config_cache_key();
}

/**
Expand Down Expand Up @@ -417,16 +417,7 @@ public function set_from_import(\stdClass $data) {
$field->save();
}
}
}

/**
* Returns a hash of the content, representing the data stored for the datasource.
*
* @return string
*/
public function get_content_hash(): string {
// Hash is stored in the DB with the cms, so gets returned by cms::get_content_hash().
return '';
$this->update_config_cache_key();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion classes/local/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public static function update_instance(\stdClass $instancedata, $mform): bool {
}

/**
* Rest the name field of cms instances.
* Reset the name field of cms instances.
*
* @param int $typeid
* @throws \coding_exception
Expand Down
29 changes: 24 additions & 5 deletions classes/local/model/cms.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,35 @@ protected static function define_properties(): array {
* Includes hashes for the CMS type and the datasources as well, as they
* contribute to what gets displayed.
*
* @deprecated
* @return string
* @throws \moodle_exception
*/
public function get_content_hash(): string {
$hash = '';
throw new \moodle_exception('This method is deprecated. Use get_cache_key instead');
}

/**
* Creates and returns a cache key. This key is a hash of the combination of the
* datasources, the CMS type and the CMS data.
*
* @return string|null
*/
public function get_cache_key(): ?string {
$key = '';
foreach (dsbase::get_datasources($this) as $ds) {
$hash .= $ds->get_content_hash();
$dskey = $ds->get_full_cache_key();
if (is_null($dskey)) {
return null;
}
$key .= $dskey;
}
$hash .= hash(lib::HASH_ALGO, serialize($this->to_record()));
$hash .= $this->get_type()->get_content_hash();
return $hash;

$key .= serialize($this->get_type()->to_record());
$key .= serialize($this->to_record());

// Return a hash to keep the key length to an acceptable size.
return hash(lib::HASH_ALGO, $key);
}

/**
Expand Down
Loading

0 comments on commit dd866fb

Please sign in to comment.