To add an extra layer of caching, use the Kontent.Ai.Delivery.Caching NuGet package. The caching is facilitated by a decorated IDeliveryClient
instance that uses an implementation of the IDeliveryCacheManager
interface to retrieve items.
There are two implementations of the IDeliveryCacheManager
interface:
MemoryCacheManager
- based on theIMemoryCache
DistributedCacheManager
- based on theIDistributedCache
Unless specified otherwise, both implementations use in-memory implementations (MemoryCache
, MemoryDistributedCache
) of the respective interfaces.
Use this approach to register the caching package for all IDeliveryClient
instances. (Order does matter.)
public void ConfigureServices(IServiceCollection services)
{
services.AddDeliveryClient(Configuration);
services.AddDeliveryClientCache(new DeliveryCacheOptions());
}
Use this approach if you wish to register the cache for a single named IDeliveryClient
instance. Please not that the order of the method calls does matter.
public void ConfigureServices(IServiceCollection services)
{
services.AddDeliveryClient("production", Configuration, "DeliveryOptions1");
services.AddDeliveryClientCache("production", new DeliveryCacheOptions());
}
CacheType
- currently allows to select fromMemory
andDistributed
DefaultExpiration
- sliding expiration time - how long the cache entry can be inactive (e.g. not accessed) before it will be removedStaleContentExpiration
- absolute expiration (timespan relative to now) for content which is yet to be refreshed on the CDNDistributedCacheResilientPolicy
- determines which resilient policy should be used whendistributed cache
is not available. Currently allows to select fromCrash
andFallbackToApi
This example shows how to use Redis cache on a local windows machine.
- Install the
Microsoft.Extensions.Caching.StackExchangeRedis
NuGet package. - Spin up an Azure Cache for Redis or install the Windows port of Redis
- Adjust
Startup.cs
// First, add Azure Redis
services.AddStackExchangeRedisCache(options =>
{
// Copy the connection string from the Access key tab in Azure Portal
options.Configuration = "<your_instance>.redis.cache.windows.net:6380,password=<your_pwd>,ssl=True,abortConnect=False";
options.InstanceName = "SampleInstance";
});
// Or local Redis cache
//services.AddStackExchangeRedisCache(options =>
//{
// options.Configuration = "localhost";
// options.InstanceName = "SampleInstance";
//});
// Second, add a DeliveryClient
services.AddDeliveryClientCache(new DeliveryCacheOptions()
{
CacheType = CacheTypeEnum.Distributed
});
You can optionally register
ILoggerFactory
implementation. Logger will have effect only whendistributed cache
is used andFallbackToApi
option is chosen forDistributedCacheResilientPolicy
parameter ofDeliveryCacheOptions
. In this case information message will be logged whendistributed cache
is not available.
Read more in Microsoft docs.
Use this approach to register the caching package for a specific DeliveryClient
instance.
var client = DeliveryClientBuilder.WithEnvironmentId("<ENVIRONMENT_ID>").Build();
var cacheOptions = Options.Create(new DeliveryCacheOptions() { DefaultExpiration = new TimeSpan(2, 0, 0) }) ;
var memoryOptions = Options.Create(new MemoryCacheOptions());
var cachedClient = new DeliveryClientCache(CacheManagerFactory.Create(new MemoryCache(memoryOptions), cacheOptions), client);
CacheManagerFactory.Create
method for theIDistributedCache
has optionalILoggerFactory loggerFactory
parameter, which has the same impact, as described forservices.AddDeliveryClientCache
method.
The default implementation of the IMemoryCache
cache contains sophisticated logic for creating cache dependencies based on linked items. This means that one can invalidate cache items not only by their own keys or keys of the collections containing them but also by the keys of their dependencies.
Explore the .NET Boilerplate to see how to invalidate cache items by cache dependencies using webhooks.
Unlike to IMemoryCache
, IDistributedCache
does not support expiration tokens. More on that here and here.
DistributedCacheEntryOptions offers absolute and sliding expiration much like MemoryCacheEntryOptions but token based expiration is absent. This makes adding cache dependencies much more of a challenge and you will need to roll your own implementation if you need this functionality.
So for cache eviction, one can only use like keys generated by CacheHelpers.GetItemKey()
and GetItemsKey()
but not GetItemsDependencyKey()
. (The same logic applies to Types, Elements, and Taxonomies.) Methods that are supposed to work fine with the distributed cache can easily be spotted in tests by searching for those marked with [InlineData(CacheTypeEnum.Distributed)]
.
Please not that it's also not possible to wipe the whole cache (which is, in a way, possible with the IMemoryCache
) and therefore, for cache invalidation, one can only rely on absolute or sliding expiration if the cached keys.
You can also provide your own version of the caching mechanism by implementing the IDeliveryCacheManager
interface.