Skip to content
martincostello edited this page Sep 28, 2023 · 14 revisions

PolicyRegistry

ℹ️ This documentation describes the previous Polly v7 API. If you are using the new v8 API, please refer to pollydocs.org.

Available from v5.2 onwards, IReadOnlyPolicyRegistry interface from v5.3, IConcurrentPolicyRegistry from v7.2.

Purpose

PolicyRegistry provides a registry for storing configured policy instances and retrieving them later for use.

PolicyRegistry promotes separation of policy definition and usage, enabling common patterns such as defining policies centrally on start-up, and accessing them at point-of-use as an injected dependency. This pattern also has benefits for unit-testing with Polly.

PolicyRegistry is also thread-safe for dynamic read/write operations. For example, you can use PolicyRegistry to manage a circuit-breaker per downstream node in dynamic distributed systems where downstream nodes (and thus policies for them) may be being added/removed dynamically.

Syntax

PolicyRegistry has Dictionary<TKey, Policy>-like semantics.

Create a registry

PolicyRegistry registry = new PolicyRegistry();
// or if using Polly with HttpClientFactory, see also https://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory
var registry = services.AddPolicyRegistry();

Populate a registry with policies

registry.Add("StandardHttpResilience", myStandardHttpResiliencePolicy);
// Or:
registry["StandardHttpResilience"] = myStandardHttpResiliencePolicy;

// Or (from Polly v7) with collection initialisation syntax:
PolicyRegistry registry = new PolicyRegistry()
{
    { "StandardHttpResilience", myStandardHttpResiliencePolicy }
};

Provide the registry to usage sites

// Pass the registry instance to usage sites by DI, perhaps
public class MyServiceGateway
{
    public void MyServiceGateway(..., IReadOnlyPolicyRegistry<string> registry, ...)
    {
       ...
    }
}

To enforce separation of registry population (typically at startup) from registry usage, you can pass the IReadOnlyPolicyRegistry<TKey> interface to call sites.

Use policies from the registry

var policy = registry.Get<IAsyncPolicy<HttpResponseMessage>>("StandardHttpResilience");
HttpResponseMessage response = await policy.ExecuteAsync<HttpResponseMessage>(...);

// Or:
HttpResponseMessage response = await
    registry.Get<IAsyncPolicy<HttpResponseMessage>>("StandardHttpResilience")
    .ExecuteAsync<HttpResponseMessage>(...);

// Or:
HttpResponseMessage response = await
    ((IAsyncPolicy<HttpResponseMessage>)registry["StandardHttpResilience"])
    .ExecuteAsync<HttpResponseMessage>(...);

Interfaces and further syntax

PolicyRegistry exposes dictionary-like semantics and behaviour.

Interface Method
IReadOnlyPolicyRegistry<TKey> bool ContainsKey(TKey key)
IReadOnlyPolicyRegistry<TKey> TPolicy Get<TPolicy>(TKey key)
IReadOnlyPolicyRegistry<TKey> bool TryGet<TPolicy>(TKey key, out TPolicy policy)
IReadOnlyPolicyRegistry<TKey> int Count
IPolicyRegistry<TKey> void Clear()
IPolicyRegistry<TKey> void Add<TPolicy>(TKey key, TPolicy policy)
IPolicyRegistry<TKey> bool Remove(TKey key)
IConcurrentPolicyRegistry<TKey> bool TryAdd<TPolicy>(TKey key, TPolicy policy)
IConcurrentPolicyRegistry<TKey> bool TryRemove<TPolicy>(TKey key, out TPolicy policy)
IConcurrentPolicyRegistry<TKey> bool TryUpdate<TPolicy>(TKey key, TPolicy newPolicy, TPolicy comparisonPolicy)
IConcurrentPolicyRegistry<TKey> TPolicy GetOrAdd<TPolicy>(TKey key, Func<TKey, TPolicy> policyFactory)
IConcurrentPolicyRegistry<TKey> TPolicy GetOrAdd<TPolicy>(TKey key, TPolicy policy)
IConcurrentPolicyRegistry<TKey> TPolicy AddOrUpdate<TPolicy>(TKey key, Func<TKey, TPolicy> addPolicyFactory, Func<TKey, TPolicy, TPolicy> updatePolicyFactory)
IConcurrentPolicyRegistry<TKey> TPolicy AddOrUpdate<TPolicy>(TKey key, TPolicy addPolicy, Func<TKey, TPolicy, TPolicy> updatePolicyFactory)

Operation

The default implementation is in-memory, backed by ConcurrentDictionary.

What does the key represent?

The default implementation is (intentionally) agnostic about what the string key represents, for maximum flexibility. Users may define their own patterns for TKey keys.

Implementing an alternative registry with IPolicyRegistry<TKey>

Polly also exposes an IPolicyRegistry<TKey> interface. You may fulfil this interface with your own implementation. This could be used, for example:

  • to provide an implementation backed by an alternative store
  • to provide an implementation with a compound TKey of some kind.
Clone this wiki locally