4

CiviCRM contains some useful caching infrastructure (confluence wiki and related question).

If I am creating a module and I would like to allow users to override the default Civi::cache() specifically for this extension how should I do that?

I think putting some settings (maybe a factory function?) in the civicrm.settings.php would be the best way? Is this correct? And any examples?

I'm thinking I could just put something like this in my code:

if (function_exists('myextension_cach_factory')) { $cache = myextension_cach_factory(); } else { $cache = Civi::cache(); }

Then the settings file could contain something like

// civicrm.settings.php function myextension_cache_factory() { return new CRM_Utils_Cache_SerializeCache(array()); }

or maybe even:

//civicrm.settings.php function myextension_cache_factory() { return new CRM_Utils_Cache_Memcached(array( 'host' => 'localhost', 'port' => 11211, 'timeout' => 3600, 'prefix' => 'mec_', )); }

Background:

$civicrm_root/CRM/Utils/Cache/Interface.php defines a minimal standard interface for caching with get(), set(), delete() and flush() methods.

$civicrm_root/CRM/Utils/Cache/ has these useful looking implementations:

APCcache.php ArrayCache.php Memcache.php Memcached.php NoCache.php SerializeCache.php SqlGroup.php

1 Answer 1

4

1. CRM_Utils_Cache::create()

When looking through the list of cache drivers, you see options like Memcache, Memcached, and Redis. Generally there's little reason why a deployment would use all three -- rather, the typical question this:

  • Do we have any kind of high-speed/shared/memory-based cache? If so, use it.
  • Do we have any kind of SQL-backed cache? If so, use it.
  • Otherwise, use an ephemeral array() (for the duration each request)

In v4.7, CRM_Utils_Cache::create() is a factory function which accepts an ordered list of drivers, and it picks the first one that's usable, e.g.

$myCache = CRM_Utils_Cache::create(array(
  'name' => 'somethingsomething',
  'type' => array('*memory*', 'SqlGroup', 'ArrayCache'),
));

This aims to address the typical use-case by making it unnecessary for the admin to configure anything extra for your specific extension.

Your extension would need to retain a copy of that cache object, e.g.

function myextension_cache() {
  if (!isset(Civi::$statics['myextension_cache'])) {
    Civi::$statics['myextension_cache'] = CRM_Utils_Cache::create(array(
      'name' => 'somethingsomething',
      'type' => array('*memory*', 'SqlGroup', 'ArrayCache'),
    ));
  }
  return Civi::$statics['myextension_cache'];
}

I believe this answers the typical requirement/issue when someone wants to configure the extension's cache, but it doesn't literally answer the question...

2. Named services and caching

The Symfony service container is a general-purpose tool for naming and tracking a bunch of objects -- cache services, database services, entity-repositories, etc. Rather than have a hundred functions like myextension_cache() which hard-code the factory, we put all the factories together in the container. This pattern improves our leverage; in principle, you can expose the container to different processes, e.g.

  • Reading multiple YAML/XML files to configure the container
  • Allowing extensions/hooks to alter the container
  • Allowing site admins to alter the container
  • Allowing dev-tools and admin-tools to inspect the container

For this reason, new caches in core tend to be created through the container, e.g.

However, at this point, the container in Civi needs improvement. For example, you can alter the container via hook_civicrm_container, but there's no YAML/XML/annotation mechanism for updating the container, and there's no mechanism for site-admins to modify services via config file (civicrm.settings.php).

The long-term goal is to shift more service-management into a container so that questions like "How does a site admin customize service X?" have a categorical answer. Improving the container is very much patch-welcome.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.