Thursday 28 January 2010

Extensible Output Caching with Velocity

This morning Scott Gu posted an article on his blog about the extensibility points now built into output caching in ASP.NET 4.0. Steve Robbins said to me that it looked easy to wire up Velocity, and I was pleased to see that when ASP.NET 4.0 ships there will be a set of samples showing how to use Velocity as an output cache provider, however since Scott said that writing an output cache provider is just a case of inheriting from System.Web.Caching.OutputCacheProvider and overriding four methods, I decided to have a look at it at lunchtime.

And it does seem remarkably simple - here's my code:
Imports Microsoft.Data.Caching
Public Class VelocityOutputCacheProvider
    Inherits System.Web.Caching.OutputCacheProvider
Private Const cacheName As String = "VelocityOutputCache"
Private mCache As DataCache
Public Sub New()
    Dim factory As DataCacheFactory

    Try
        factory = New DataCacheFactory

        mCache = factory.GetCache(cacheName)
    Catch ex As Exception
        Throw
    Finally
        factory = Nothing
    End Try
End Sub

Public Overrides Function Add(ByVal key As String, ByVal entry As Object, ByVal utcExpiry As Date) As Object
    Try
        mCache.Add(key, entry, (utcExpiry - DateTime.UtcNow))
    Catch ex As Exception
        Throw
    Finally
    End Try
End Function

Public Overrides Sub Remove(ByVal key As String)
    Try
        Call mCache.Remove(key)
    Catch ex As Exception
        Throw
    Finally
    End Try
End Sub
Public Overrides Function [Get](ByVal key As String) As Object
Dim cachedObject As Object
    Try
        cachedObject = mCache.Get(key)
        Return cachedObject
    Catch ex As Exception
       Throw
    Finally
    End Try
End Function
Public Overrides Sub [Set](ByVal key As String, ByVal entry As Object, ByVal utcExpiry As Date)
    Try
        Call mCache.Put(key, entry, (utcExpiry - DateTime.UtcNow))
    Catch ex As Exception
        Throw
    Finally
    End Try
    End Sub
End Class

The only thing I'm a little fuzzy on is what object the Add method should return. It's slightly awkward that the Velocity Cache.Add method takes a TimeSpan parameter where the OutputCacheProvider passes in a point in time, so I've calculated a TimeSpan by subtracting the current time from the passed-in Date.
 
Something that's slightly unclear is how this would behave in a server farm. It depends whether each server maintains it's own set of cached pages, or the cached pages are common and available to all servers. If the latter then this would be a truly awesome boost to scalability since for any given web page only the first server that picked up a request for a given URL would need to compile it - other servers in the farm would then be able to pick up the cached copy and return it to the client.

Update: When the Add method is called, you don't need to return anything, just put the object into the cache and ASP.NET takes care of the rest. You get a warning that the function doesn't return anything but this can be ignored.

No comments: