Skip to content

Plug-in for the Polly Cache policy supporting Microsoft.Extensions.Caching.Distributed.IDistributedCache.

License

Notifications You must be signed in to change notification settings

App-vNext/Polly.Caching.IDistributedCache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Polly.Caching.Distributed

This repo contains the Microsoft.Extensions.Caching.Distributed.IDistributedCache provider for the Polly Cache policy. The current version targets .NET Standard 1.1, .NET Standard 2.0 and .NET Standard 2.1.

NuGet version Build status Slack Status

What is Polly?

Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, Cache aside and Fallback in a fluent and thread-safe manner.

Polly is a member of the .NET Foundation.

Keep up to date with new feature announcements, tips & tricks, and other news through www.thepollyproject.org

What is Polly.Caching.Distributed?

This project, Polly.Caching.Distributed, allows you to use Polly's CachePolicy with implementations of .Net Standard's IDistributedCache.

Installing Polly.Caching.Distributed via NuGet

Install-Package Polly.Caching.Distributed

Supported targets

Polly.Caching.Distributed >= v3.0.1 supports .NET Standard 1.1, .NET Standard 2.0 and .NET Standard 2.1.

Polly.Caching.Distributed < v3.0.1 supports .NET Standard 1.1 and .NET Standard 2.0.

Dependency compatibility with Polly

Polly.Caching.Distributed >=v3.0.1 requires:

Polly.Caching.Distributed v3.0.0 requires:

Polly.Caching.Distributed >=v2.0 and <v3 requires:

  • Polly >= v6.0.1 and <v7.

Polly.Caching.IDistributedCache <v2.0 requires:

How to use the Polly.Caching.Distributed plugin

These notes assume you are familiar with using the .Net Standard IDistributedCache implementations. For information, see: https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed . As described on that page, Microsoft provide a Redis implementation and an SQL server implementation for IDistributedCache.

Assuming you have an instance IDistributedCache distributedCache in hand (perhaps just configured and instantiated, perhaps provided to local code by Dependency Injection):

// Create a Polly cache policy for caching string results, using that IDistributedCache  instance.
var cachePolicy = Policy.Cache<string>(distributedCache.AsSyncCacheProvider<string>(), TimeSpan.FromMinutes(5));

// Create a Polly cache policy for caching byte[] results, using that IDistributedCache  instance.
var cachePolicy = Policy.Cache<byte[]>(distributedCache.AsSyncCacheProvider<byte[]>(), TimeSpan.FromMinutes(5));

// Or similarly for async executions returning string results:
var cachePolicy = Policy.CacheAsync<string>(distributedCache.AsAsyncCacheProvider<string>(), TimeSpan.FromMinutes(5));

// Or similarly for async executions returning  byte[] results:
var cachePolicy = Policy.CacheAsync<byte[]>(distributedCache.AsAsyncCacheProvider<byte[]>(), TimeSpan.FromMinutes(5));

// You can also use ASP.NET Core's DistributedCacheEntryOptions for specifying cache item time-to-live, as shown below. 
// All time-to-live functionality represented by DistributedCacheEntryOptions is supported.
DistributedCacheEntryOptions entryOptions = // ...
var cachePolicy = Policy.CacheAsync<byte[]>(distributedCache.AsAsyncCacheProvider<byte[]>(), entryOptions.AsTtlStrategy());
 

Configuration via DI in ASPNET Core:

// In this example we choose to pass a whole PolicyRegistry by dependency injection rather than the individual policy, on the assumption the webapp will probably use multiple policies across the app.

// For example: 
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedRedisCache(options =>
        {
            options.Configuration = "localhost"; // or whatever
            options.InstanceName = "SampleInstance";
        });

        services.AddSingleton<Polly.Caching.IAsyncCacheProvider<string>>(serviceProvider => serviceProvider.GetRequiredService<IDistributedCache>().AsAsyncCacheProvider<string>());

        services.AddSingleton<Polly.Registry.IReadOnlyPolicyRegistry<string>, Polly.Registry.PolicyRegistry>((serviceProvider) =>
        {
            PolicyRegistry registry = new PolicyRegistry();
            registry.Add("myCachePolicy", Policy.CacheAsync<string>(serviceProvider.GetRequiredService<IAsyncCacheProvider<string>>(), TimeSpan.FromMinutes(5)));

            return registry;
            });

        // ...
    }
}

// In a controller, inject the policyRegistry and retrieve the policy:
// (magic string "myCachePolicy" hard-coded here only to keep the example simple) 
public MyController(IReadOnlyPolicyRegistry<string> policyRegistry)
{
    var _cachePolicy = policyRegistry.Get<IAsyncPolicy<string>>("myCachePolicy"); 
    // ...
}

Automatically serializing more complex type

The raw cache provider Polly.Caching.IDistributedCache allows you to cache items of type byte[] or string as those are the native formats supported by Microsoft.Extensions.Caching.Distributed.IDistributedCache. However, Polly also allows you to automatically serialize more complex types.

The package Polly.Caching.Serialization.Json (github; nuget) is a Polly ICacheItemSerializer<TResult, string> to serialize any type for use with Polly.Caching.IDistributedCache.

Configuration in .NET Core:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedRedisCache(options =>
        {
            options.Configuration = "localhost"; // or whatever
            options.InstanceName = "SampleInstance";
        });

        // Obtain a Newtonsoft.Json.JsonSerializerSettings defining any settings to use for serialization
        // (could alternatively be obtained from a factory by DI)
        var serializerSettings = new JsonSerializerSettings()
        {
            // Any configuration options
        };

        // Register a Polly cache provider for caching ProductDetails entities, using the IDistributedCache instance and a Polly.Caching.Serialization.Json.JsonSerializer.
        // (ICacheItemSerializer<ProductDetails, string> could alternatively be obtained from a factory by DI)
        services.AddSingleton<Polly.Caching.IAsyncCacheProvider<ProductDetails>>(serviceProvider =>
            serviceProvider
                .GetRequiredService<IDistributedCache>()
                .AsAsyncCacheProvider<string>()
                .WithSerializer<ProductDetails, string>(
                    new Polly.Caching.Serialization.Json.JsonSerializer<ProductDetails>(serializerSettings)
                );

        // Register a Polly cache policy for caching ProductDetails entities, using that IDistributedCache instance.
        services.AddSingleton<Polly.Registry.IReadOnlyPolicyRegistry<string>, Polly.Registry.PolicyRegistry>((serviceProvider) =>
        {
            PolicyRegistry registry = new PolicyRegistry();
            registry.Add("productsCachePolicy", Policy.CacheAsync<ProductDetails>(serviceProvider.GetRequiredService<IAsyncCacheProvider<ProductDetails>>(), TimeSpan.FromMinutes(5)));

            return registry;
        });

        // ...
    }
}

// In a controller, inject the policyRegistry and retrieve the policy:
// (magic string "productsCachePolicy" hard-coded here only to keep the example simple) 
public MyController(IReadOnlyPolicyRegistry<string> policyRegistry)
{
    var _cachePolicy = policyRegistry.Get<IAsyncPolicy<ProductDetails>>("productsCachePolicy"); 
    // ...
}

Usage at the point of consumption

string productId = // ... from somewhere
string productDescription = await _cachePolicy.ExecuteAsync(context => getProductDescription(productId), 
    new Context(productId) // productId will also be the cache key used in this execution.
); 

For many more configuration options and usage examples of the main Polly CachePolicy, see the main Polly readme and deep doco on the Polly wiki. Additional overloads allow attaching delegates for cache errors, cache hits/misses etc, for logging and telemetry.

CachePolicy can of course also be combined with other policies in a PolicyWrap.

Release notes

For details of changes by release see the change log.

Acknowledgements

Instructions for Contributing

Please check out our Wiki for contributing guidelines. We are following the excellent GitHub Flow process, and would like to make sure you have all of the information needed to be a world-class contributor!

Since Polly is part of the .NET Foundation, we ask our contributors to abide by their Code of Conduct.

Also, we've stood up a Slack channel for easier real-time discussion of ideas and the general direction of Polly as a whole. Be sure to join the conversation today!

License

Licensed under the terms of the New BSD License