Huhh, quite a time since the last post, so many things to care about as the planned release commences. Last week we've finalized the cache implementation of the Sense/Net Portal Engine TNG so I decided to share some of its more important or interesting aspects.
“Cache to support NLBS and clusters”
First of all, TNG caching will support cache synchronization in distributed installation scenarios, for example Network Load Balance Services (NLBS) is used or the WebGarden feature is set. For this we provide a a cross AppDomain notification system we call Cluster Messaging. Being able to totally rely on caching even in a multi AppDomain environment is a vital feature of a portal framework if it wants to provide superb performance.
Caching functionality and the Cache class will be supported in both web and non-web environments. The .NET framework only provides caching for ASP.NET applications and we found this a limitation we needed to circumvent. So our Cache class is always there regardless of application type whenever the PortalEngine assemblies are used.
Whenever possible our cache functionality merely wraps the HttpContext.Current.Cache class to extend it with the features detailed below.
Support for the System.Web.Caching.CacheDependency class
Automatic cache invalidation for cache content that relies on the PFS data store using the PfsNodeDependency class that subclasses CacheDependency.
The “Comments” portlet renders a list of Comment nodes associated with the Content node. If the Content is frequently read but occasionally commented we will have a great bunch of repeated sql queries and expensive output transformations that return the exactly same output time to time. Therefore, we will cache the portlet output and only render it again if the underlying data changes.
public override void Render(HtmlWriter writer)
string CacheKey = this.ContentNodePath + “-comments”;
string html = (string)PortalEngine.DistributedApplication.Cache[CacheKey];
if (html == null)
StringBuilder sb = new StringBuilder();
Node content = Node.Load(this.ContentNodePath);
Node comments = Content.Comments.ToArray();
AggregateCacheDependency dependencies = new AggregateCacheDependency();
foreach(Node comment in comments)
//should the comment node change by any reason we will be notified
//when someone writes a new comment thus altering the Content.Comments collection, our Content
//node is considered changed and the distributed cache is notified to invalidate the referring cache items
html = sb.ToString();
PortalEngine.DistributedApplication.Cache.Insert(CacheKey, html, dependencies);