<PackageReference Include="Polly.Core" Version="8.5.2" />

ResiliencePipelineRegistry<TKey>

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."); } } }