Telligent Community 6.0 custom caching

In this article I will be briefly describing a custom caching approach which I developed for custom Telligent Community 6.0 widgets. Understanding caching and anticipating issues with cache is important to keep the load time of widgets and pages in check.

Widgets within Telligent are cached for five seconds out-of-the-box. This is a balance between performance gains by not having to re-evaluate the widget code and preventing the content of the widget becoming stale. While the five second cache is fine for most widgets out there, there are some widgets which may require additional caching to reduce load. Examples are widgets that perform many expensive database queries or connect to external API’s.

To illustrate how many expensive database queries can cause high load times for widgets I will describe a widget a recently developed for a client. This custom widget provides an overview of the amount of content within the community to give the user an indication of how active the groups within the community are. The community has ten groups, with a total of fifty sub groups. These groups contain roughly five hundred threads and twenty-five hundred replies. Querying all this content causes high load on the database server and increases load time for the widget. We remedied this problem by enhancing the caching. While this is not the only possible form of improvement, this article will only discuss caching.

There are two approaches known to me to increase caching within Telligent. The first approach is changing the standard Telligent caching through the caching.config. For more information see the documentation. I would like to point out that changes to the standard Telligent caching effect everything that is put into the cache. If you require only a portion of the widgets to be cached for a longer period of time, changing the standard Telligent caching probably yields undesirable results in other parts of the community.

The second approach requires customization through an extension, but you can achieve a more fine grained control over caching than you can with changing the standard caching. If you want to cache a portion of the widgets for ten minutes, and leave the rest on the standard five second caching, this approach is the way to go. If this is your first time writing an extension for Telligent Community 6.0, this article by Adam Seabridge is a good read. Basically what we want to do is write our own extension to handle caching for us and enable us to determine how long an object remains in the cache. The extension will look like this:

using System;

using Telligent.Evolution.Extensibility.Caching.Version1;

namespace KvKVelocityScriptExtensions
{

    public class CachingVelocityScriptExtensions : Telligent.Evolution.Extensibility.UI.Version1.IScriptedContentFragmentExtension
    {

        public string Name
        {
            get { return "KvK Cache Extension Plugin"; }
        }

        public string ExtensionName
        {
            get { return "KvKCachingExtension"; }
        }

        public string Description
        {
            get { return "Caching Extension Class For Use In Custom Widgets"; }
        }

        public void Initialize()
        {
            //stuff here;
        }

        public object Extension
        {
            //pass back an instance of the TwitterService which exposes the methods
            get { return new CachingService(); }
        }
    }

    public class CachingService
    {
        #region GroupStatistics

        public const string KvKGroupListWidgetCacheKeyPrefix = "KVKGROUPLISTWIDGET{0}";

        public GroupStatistics GetGroupStatistics(int groupId) 
        {
            string cacheKey = string.Format(KvKGroupListWidgetCacheKeyPrefix, groupId);
            GroupStatistics groupstatics = (GroupStatistics)CacheService.Get(cacheKey, CacheScope.All);

            if (groupstatics != null) {
                return groupstatics;
            }

            return null;
        }

        public void PutGroupStatistics(int groupId, int minutesToCache, int forumThreadCount, int forumThreadReplyCount, DateTime lastForumThreadReply)
        {
            string cacheKey = string.Format(KvKGroupListWidgetCacheKeyPrefix, groupId);
            GroupStatistics groupStatistics = new GroupStatistics
            {
                ForumThreadCount = forumThreadCount, 
                ForumThreadReplyCount = forumThreadReplyCount, 
                LastForumThreadReply = lastForumThreadReply
            };

            CacheService.Put(cacheKey, groupStatistics, CacheScope.All, null, TimeSpan.FromMinutes(minutesToCache));
        }

        #endregion
    }

    public class GroupStatistics
    {
        public int ForumThreadCount { get; set; }
        public int ForumThreadReplyCount { get; set; }
        public DateTime LastForumThreadReply { get; set; }
    }

}

As the code above shows, we make a simple extension with some simple functions that interact with Telligent caching. As you cannot cast objects within Velocity script, the functions within your caching extension have to return concrete instances of objects, in this case an instance of the GroupStatistics class. You have to write a small amount of additional code when want to cache an additional type of object. Now that we got our simple extension added to Telligent Community 6.0 we can start using it from Velocity script like this:

#foreach($group in $groups)
	#set($groupStatistics = $CachingExtension.GetGroupStatistics($group.Id))
	#if ($groupStatistics)
		## Use cached results.
	#else
		## Execute normal widget code.
		## Insert results into cache.
		$CachingExtension.PutGroupStatistics($group.Id, 15, $threadCount, $replyCount, $lastReactionDate)
	#end
#end

While this solution takes some additional effort, it adds great value over the standard Telligent caching in that it gives developers to power to cache widgets individuality to their needs. While caching is not the answer to every performance issue, adding additional caching in the right places can reduce load on the servers and help keep page loads in check. If you have any questions feel free to leave a comment or contact me.

2 thoughts on “Telligent Community 6.0 custom caching

  1. I’d recommend that you use Telligent.Evolution.Extensibility.Caching.Version1.CacheService rather than Telligent.Evolution.Components.CacheService. Using anything outside of the Telligent.Evolution.Extensibility namespace is not upgrade safe and could be renamed/changed/removed at any time. By using the cache service inside the Extensibility namespace, you can better upgrade proff your widget

    • Alex, thank you for pointing out this opportunity for improvement, i updated the extension and the blog post. The suggestion to utilize the Telligent.Evolution.Extensibility namespace whenever possible is something I will remember for future customizations that require a .Net component.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>