Implementing a Custom Client Cache
If the four types of client caches provided by the Scaleout.Client library do not meet your requirements, a custom client cache can by implemented by inheriting from the ClientCache<TValue> class.
Procedure
- Client cache implementations must be thread safe.
- The
TValue
type parameter to the base ClientCache class must match the type of values being stored in the Cache instances that use the implementation.
Example
The following example implements a custom client cache and uses the .NET Framework's System.Runtime.Caching.MemoryCache to store object references.
Implementing the Custom Client Cache
using System;
using System.Text;
using System.Runtime.Caching;
using Scaleout.Client.Net;
using Scaleout.Client.InProc;
namespace CustomClientCache
{
/// <summary>
/// Allows a <see cref="System.Runtime.Caching.MemoryCache"/> instance to be used
/// as an in-process client cache for a Scaleout.Client.Cache.
/// </summary>
public class MemoryCacheAdapter<TValue> : ClientCache<TValue>
{
public MemoryCache MemoryCache { get; private set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="memoryCache">System.Runtime.Caching.MemoryCache instance.</param>
public MemoryCacheAdapter(MemoryCache memoryCache)
{
MemoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
}
// Converts a ScaleOut ObjectKey identifier to a string that
// can be used as a System.Runtime.Caching.MemoryCache string key.
private static string KeyToString(ref ObjectKey key)
{
return Convert.ToBase64String(key.ToByteArray());
}
public override CacheEntry<TValue> Get(ref ObjectKey objectKey)
{
string key = KeyToString(ref objectKey);
// Returning null is OK; null tells the Scaleout.Client library
// that the item wasn't found.
return MemoryCache.Get(key) as CacheEntry<TValue>;
}
public override void Remove(ref ObjectKey objectKey)
{
string key = KeyToString(ref objectKey);
MemoryCache.Remove(key);
}
public override void Set(ref ObjectKey objectKey, CacheEntry<TValue> cacheEntry)
{
string key = KeyToString(ref objectKey);
// Passing null policy to use the MemoryCache's default.
MemoryCache.Set(key, cacheEntry, policy: null);
}
public override void Touch(ref ObjectKey objectKey)
{
var entry = Get(ref objectKey);
entry?.Touch(DateTime.UtcNow);
}
}
}
Using the Custom Client Cache
Use CacheBuilder.SetClientCache to register a custom client cache with a Cache instance.
using Scaleout.Client;
using Scaleout.Client.InProc;
using System;
using System.Collections.Specialized;
using System.Runtime.Caching;
public class Program
{
public void Main()
{
var conn = GridConnection.Connect("bootstrapGateways=localhost:721");
// Configure the .NET MemoryCache to trim memory every 15 seconds.
var memCacheConfig = new NameValueCollection();
memCacheConfig.Add("cacheMemoryLimitMegabytes", "100"); // 100 MB
memCacheConfig.Add("pollingInterval", "00:00:15"); // 15 seconds (default is 2 mins)
var memCache = new MemoryCache("ScaleOut MemoryCache", memCacheConfig);
// Register the custom client cache using the CacheBuilder.
var memCacheAdapter = new MemoryCacheAdapter<MyClass>(memCache);
var cb = new CacheBuilder<string, MyClass>("My Cache", conn)
.SetClientCache(memCacheAdapter);
var cache = cb.Build();
//...
}
}