Sitecore custom cache that is cleared on publish

In this article I will demonstrate how to create a custom Sitecore cache and how to ensure that it is cleared when you publish.

First I will create the simplest custom cache available:

namespace MyNamespace
{
  public class MyCustomCache : CustomCache
  {
    public MyCustomCache(string name, long maxSize) : base("MyCustomCache." + name, maxSize)
    {
    }

    public string Get(string cacheKey)
    {
      return GetString(cacheKey);
    }

    public void Set(string cacheKey, string value)
    {
      SetString(cacheKey, value);
    }
  }
}

The cache is instantiated with a name, meaning that you can use the class to create more than one cache, as long as you remember to give each instance its own name.

The cache contains a string as key and returns a string as value. It is used like this (pseudocode):

// Instantiation, set up an 1MB cache
private MyCustomCache myCustomCache = new MyCustomCache("CacheName", StringUtil.ParseSizeString("1MB"));

// Get value from cache
string myValue = myCustomCache.Get(myKey);

// Set value in cache
myCustomCache.Set(myKey, myValue);
  

To clear the cache on publish, we need to set up an event handler on either publish:end and publish:end:remote or publish:complete and publish:complete:remote.

There is a little confusion as to when in the publish pipeline these events are fired. In previous versions (prior to Sitecore 7.2), publish:end and publish:end:remote was fired for each language and each target, and publish:complete and publish:complete:remote was fired when the publish job was done. But in later versions, publish:end and publish:end:remote is also only fired once.

The :remote events (publish:end:remote and publish:complete:remote) is fired on your remote (i.e. CD servers) by the way.

Enough talk, lets code the cache clearer. First I will set up the 2 new events on publish:end and publish:end:remote:

<events>
  <event name="publish:end">
    <handler type="MyNamespace.MyCacheClearer, Mydll" method="ClearCaches">
      <caches hint="list">
        <cache>MyCustomCache.CacheName</cache>
      </caches>
    </handler>
  </event>
  <event name="publish:end:remote">
    <handler type="MyNamespace.MyCacheClearer, Mydll" method="ClearCaches">
      <caches hint="list">
        <cache>MyCustomCache.CacheName</cache>
      </caches>
    </handler>
  </event>
</events>

The events will now call the method ClearCaches on the Mynamespace.MyCacheClearer class:

namespace MyNamespace
{
  public class MyCacheClearer 
  {
    public void ClearCaches(object sender, EventArgs args)
    {
      Assert.ArgumentNotNull(sender, "sender");
      Assert.ArgumentNotNull(args, "args");
      try
      {
        DoClear();
      }
      catch (Exception ex)
      {
        Log.Error(this + ": " + ex, ex, this);
      }
    }

    private void DoClear()
    {
      foreach (string cacheName in Caches)
      {
        Cache cache = CacheManager.FindCacheByName(cacheName);
        if (cache == null)
          continue;
        Log.Info(this + ". Clearing " + cache.Count + " items from " + cacheName, this);
        cache.Clear();
      }
    }

    private readonly ArrayList _caches = new ArrayList();
    public ArrayList Caches
    {
      get
      {
        return this._caches;
      }
    }
  }
}

The DoClear() method uses the <caches> list from the configuration to find which caches to clear. You should write the names of each of the caches to be cleared in the configuration.

FINAL NOTES:

The caches are first created when instantiated and the first element is added. That is why it is not available in the /sitecore/admin/cache.aspx administration tool on Sitecore startup.

MORE TO READ:

 

Advertisements

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in c#, General .NET, Sitecore 6, Sitecore 7, Sitecore 8 and tagged , , , , , , , . Bookmark the permalink.

5 Responses to Sitecore custom cache that is cleared on publish

  1. Hey Brian, interestingly in 8.2 I _never_ see the cache in the `cache.aspx` page using this method, even after things are added. The admin page asks the `CacheManager` to display all its configured caches via the method `GetAllCaches()`. When I execute that in a watch window, there’s 122 (including mine) but the admin page only reports 117 – 5 are going missing somewhere and I’ve no idea why… yet

  2. OK Brian, it turns out that the CacheAdmin page goes looking for an ICacheInfo interface and the CustomCache base class does not actually implement this. The whole thing is a facade anyway so you can easily implement the ICacheInfo by forwarding all the members to `this.InnerCache`.

  3. UPDATE :: Brian if you’re reading this you can delete the above comments. Anyone else, I was looking in the wrong spot (I had two app domains – best not to ask why). Interesting side-notes: 1) If you override `Clear()` on your CustomCache it is *not* called by the Admin page; 2) There doesn’t appear to be any hook to respond to a `CacheClear` event anywhere; 3) ICacheInfo is implemented in an internal `Cache` object that is connected to your named cache by the `CacheManger`; 4) If you want Sitecore to use your cache class instead of the internal one you need to implement the ICache interface and add a child element to the config node with the same name as your cache and normal type specifier conventions (it uses the std Sitecore factory)… phew!

  4. That last comment should have a reference to an xml element called “cacheContainerConfiguration” but it was filtered out. In 8.2 (only) find it in the “CacheContainers.config.example” file

  5. Pingback: Sitecore Caching – Clear caches individually | Brian Pedersen's Sitecore and .NET Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s