delivery-sdk-net

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:

Unless specified otherwise, both implementations use in-memory implementations (MemoryCache, MemoryDistributedCache) of the respective interfaces.

Registration using DI

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());
}

Selective registration

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());
}

DeliveryCacheOptions

Distributed caching - example

This example shows how to use Redis cache on a local windows machine.

  1. Install the Microsoft.Extensions.Caching.StackExchangeRedis NuGet package.
  2. Spin up an Azure Cache for Redis or install the Windows port of Redis
  3. Adjust Startup.cs ```csharp // First, add Azure Redis services.AddStackExchangeRedisCache(options => { // Copy the connection string from the Access key tab in Azure Portal options.Configuration = “.redis.cache.windows.net:6380,password=,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](/delivery-sdk-net/configuration/dependency-injection.html). Logger will have effect only when `distributed cache` is used and [`FallbackToApi`](../../Kontent.Ai.Delivery.Caching/DistributedCacheResilientPolicy.cs) option is chosen for `DistributedCacheResilientPolicy` parameter of `DeliveryCacheOptions`. In this case information message will be logged when `distributed cache` is not available.

Read more in [Microsoft docs](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed).

## Usage without DI

Use this approach to register the caching package for a specific `DeliveryClient` instance.

```csharp
   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 the IDistributedCache has optional ILoggerFactory loggerFactory parameter, which has the same impact, as described for services.AddDeliveryClientCache method.

Cache eviction / cache item invalidation

MemoryCacheManager

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.

DistributedCacheManager

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.

Customizing caching

You can also provide your own version of the caching mechanism by implementing the IDeliveryCacheManager interface.