ResiliencePipelineRegistry<TKey>
public sealed class ResiliencePipelineRegistry<TKey> : ResiliencePipelineProvider<TKey>, IDisposable, IAsyncDisposable
Represents a registry of resilience pipelines and builders that are accessible by TKey.
using Polly.Utils;
using Polly.Utils.Pipeline;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace Polly.Registry
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public sealed class ResiliencePipelineRegistry<TKey> : ResiliencePipelineProvider<TKey>, IDisposable, IAsyncDisposable
{
[System.Runtime.CompilerServices.Nullable(0)]
private sealed class GenericRegistry<[System.Runtime.CompilerServices.Nullable(2)] TResult> : IAsyncDisposable
{
private readonly Func<ResiliencePipelineBuilder<TResult>> _activator;
private readonly ConcurrentDictionary<TKey, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>>> _builders;
private readonly ConcurrentDictionary<TKey, ResiliencePipeline<TResult>> _pipelines;
private readonly Func<TKey, string> _builderNameFormatter;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})]
private readonly Func<TKey, string> _instanceNameFormatter;
public GenericRegistry(Func<ResiliencePipelineBuilder<TResult>> activator, IEqualityComparer<TKey> builderComparer, IEqualityComparer<TKey> strategyComparer, Func<TKey, string> builderNameFormatter, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})] Func<TKey, string> instanceNameFormatter)
{
_activator = activator;
_builders = new ConcurrentDictionary<TKey, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>>>(builderComparer);
_pipelines = new ConcurrentDictionary<TKey, ResiliencePipeline<TResult>>(strategyComparer);
_builderNameFormatter = builderNameFormatter;
_instanceNameFormatter = instanceNameFormatter;
}
public bool TryGet(TKey key, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out ResiliencePipeline<TResult> strategy)
{
if (_pipelines.TryGetValue(key, out strategy))
return true;
if (_builders.TryGetValue(key, out Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>> value)) {
strategy = GetOrAdd(key, value);
return true;
}
strategy = null;
return false;
}
public ResiliencePipeline<TResult> GetOrAdd(TKey key, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>> configure)
{
new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _instanceNameFormatter?.Invoke(key));
return _pipelines.GetOrAdd(key, delegate(TKey k) {
(ResilienceContextPool ContextPool, PipelineComponent Component) valueTuple = new RegistryPipelineComponentBuilder<ResiliencePipelineBuilder<TResult>, TKey>(_activator, k, _builderNameFormatter(k), _instanceNameFormatter?.Invoke(k), configure).CreateComponent();
return new ResiliencePipeline<TResult>(pool: valueTuple.ContextPool, component: valueTuple.Component, disposeBehavior: DisposeBehavior.Reject);
});
}
public bool TryAddBuilder(TKey key, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>> configure)
{
return _builders.TryAdd(key, configure);
}
[AsyncStateMachine(typeof(GenericRegistry<>.<DisposeAsync>d__9))]
public ValueTask DisposeAsync()
{
<DisposeAsync>d__9 stateMachine = default(<DisposeAsync>d__9);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<DisposeAsync>d__9>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
}
private readonly Func<ResiliencePipelineBuilder> _activator;
private readonly ConcurrentDictionary<TKey, Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>>> _builders;
private readonly ConcurrentDictionary<TKey, ResiliencePipeline> _pipelines;
private readonly ConcurrentDictionary<Type, object> _genericRegistry = new ConcurrentDictionary<Type, object>();
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})]
private readonly Func<TKey, string> _instanceNameFormatter;
private readonly Func<TKey, string> _builderNameFormatter;
private readonly IEqualityComparer<TKey> _builderComparer;
private readonly IEqualityComparer<TKey> _pipelineComparer;
private bool _disposed;
public ResiliencePipelineRegistry()
: this(new ResiliencePipelineRegistryOptions<TKey>())
{
}
public ResiliencePipelineRegistry(ResiliencePipelineRegistryOptions<TKey> options)
{
Guard.NotNull<ResiliencePipelineRegistryOptions<TKey>>(options, "options");
Guard.NotNull<Func<ResiliencePipelineBuilder>>(options.BuilderFactory, "options.BuilderFactory");
Guard.NotNull<IEqualityComparer<TKey>>(options.PipelineComparer, "options.PipelineComparer");
Guard.NotNull<IEqualityComparer<TKey>>(options.BuilderComparer, "options.BuilderComparer");
Guard.NotNull<Func<TKey, string>>(options.BuilderNameFormatter, "options.BuilderNameFormatter");
_activator = options.BuilderFactory;
_builders = new ConcurrentDictionary<TKey, Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>>>(options.BuilderComparer);
_pipelines = new ConcurrentDictionary<TKey, ResiliencePipeline>(options.PipelineComparer);
_instanceNameFormatter = options.InstanceNameFormatter;
_builderNameFormatter = options.BuilderNameFormatter;
_builderComparer = options.BuilderComparer;
_pipelineComparer = options.PipelineComparer;
}
public override bool TryGetPipeline<[System.Runtime.CompilerServices.Nullable(2)] TResult>(TKey key, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out ResiliencePipeline<TResult> pipeline)
{
this.EnsureNotDisposed();
return GetGenericRegistry<TResult>().TryGet(key, out pipeline);
}
public override bool TryGetPipeline(TKey key, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out ResiliencePipeline pipeline)
{
EnsureNotDisposed();
if (_pipelines.TryGetValue(key, out pipeline))
return true;
if (_builders.TryGetValue(key, out Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>> value)) {
pipeline = GetOrAddPipeline(key, value);
return true;
}
pipeline = null;
return false;
}
public ResiliencePipeline GetOrAddPipeline(TKey key, Action<ResiliencePipelineBuilder> configure)
{
Guard.NotNull<Action<ResiliencePipelineBuilder>>(configure, "configure");
EnsureNotDisposed();
return GetOrAddPipeline(key, delegate(ResiliencePipelineBuilder builder, ConfigureBuilderContext<TKey> _) {
configure(builder);
});
}
public ResiliencePipeline GetOrAddPipeline(TKey key, Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>> configure)
{
Guard.NotNull<Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>>>(configure, "configure");
EnsureNotDisposed();
if (_pipelines.TryGetValue(key, out ResiliencePipeline value))
return value;
return _pipelines.GetOrAdd(key, delegate(TKey k) {
(ResilienceContextPool ContextPool, PipelineComponent Component) valueTuple = new RegistryPipelineComponentBuilder<ResiliencePipelineBuilder, TKey>(_activator, k, _builderNameFormatter(k), _instanceNameFormatter?.Invoke(k), configure).CreateComponent();
return new ResiliencePipeline(pool: valueTuple.ContextPool, component: valueTuple.Component, disposeBehavior: DisposeBehavior.Reject);
});
}
public ResiliencePipeline<TResult> GetOrAddPipeline<[System.Runtime.CompilerServices.Nullable(2)] TResult>(TKey key, Action<ResiliencePipelineBuilder<TResult>> configure)
{
Guard.NotNull<Action<ResiliencePipelineBuilder<TResult>>>(configure, "configure");
this.EnsureNotDisposed();
return GetOrAddPipeline(key, delegate(ResiliencePipelineBuilder<TResult> builder, ConfigureBuilderContext<TKey> _) {
configure(builder);
});
}
public ResiliencePipeline<TResult> GetOrAddPipeline<[System.Runtime.CompilerServices.Nullable(2)] TResult>(TKey key, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>> configure)
{
Guard.NotNull<Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>>>(configure, "configure");
this.EnsureNotDisposed();
return GetGenericRegistry<TResult>().GetOrAdd(key, configure);
}
public bool TryAddBuilder(TKey key, Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>> configure)
{
Guard.NotNull<Action<ResiliencePipelineBuilder, ConfigureBuilderContext<TKey>>>(configure, "configure");
EnsureNotDisposed();
return _builders.TryAdd(key, configure);
}
public bool TryAddBuilder<[System.Runtime.CompilerServices.Nullable(2)] TResult>(TKey key, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>> configure)
{
Guard.NotNull<Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>>>(configure, "configure");
this.EnsureNotDisposed();
return GetGenericRegistry<TResult>().TryAddBuilder(key, configure);
}
public void Dispose()
{
DisposeAsync().AsTask().GetAwaiter().GetResult();
}
[AsyncStateMachine(typeof(ResiliencePipelineRegistry<>.<DisposeAsync>d__20))]
public ValueTask DisposeAsync()
{
<DisposeAsync>d__20 stateMachine = default(<DisposeAsync>d__20);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<DisposeAsync>d__20>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[System.Runtime.CompilerServices.NullableContext(2)]
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0,
1
})]
private GenericRegistry<TResult> GetGenericRegistry<TResult>()
{
if (this._genericRegistry.TryGetValue(typeof(TResult), out object value))
return (GenericRegistry<TResult>)value;
return (GenericRegistry<TResult>)this._genericRegistry.GetOrAdd(typeof(TResult), (Func<Type, object>)((Type _) => new GenericRegistry<TResult>((Func<ResiliencePipelineBuilder<TResult>>)(() => new ResiliencePipelineBuilder<TResult>((ResiliencePipelineBuilderBase)this._activator())), this._builderComparer, this._pipelineComparer, this._builderNameFormatter, this._instanceNameFormatter)));
}
private void EnsureNotDisposed()
{
if (_disposed)
throw new ObjectDisposedException("ResiliencePipelineRegistry", "The resilience pipeline registry has been disposed and cannot be used anymore.");
}
}
}