Skip to content

Commit

Permalink
Cleanup ResiliencePipelineRegistry internals (#1510)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk committed Aug 23, 2023
1 parent 282297e commit 32a3390
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 41 deletions.
72 changes: 72 additions & 0 deletions src/Polly.Core/Registry/RegistryPipelineComponentBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Polly.Telemetry;
using Polly.Utils.Pipeline;

namespace Polly.Registry;

/// <summary>
/// Builds a <see cref="PipelineComponent"/> used by the registry.
/// </summary>
internal class RegistryPipelineComponentBuilder<TBuilder, TKey>
where TBuilder : ResiliencePipelineBuilderBase
where TKey : notnull
{
private readonly Func<TBuilder> _activator;
private readonly TKey _key;
private readonly string _builderName;
private readonly string? _instanceName;
private readonly Action<TBuilder, ConfigureBuilderContext<TKey>> _configure;

public RegistryPipelineComponentBuilder(
Func<TBuilder> activator,
TKey key,
string builderName,
string? instanceName,
Action<TBuilder, ConfigureBuilderContext<TKey>> configure)
{
_activator = activator;
_key = key;
_builderName = builderName;
_instanceName = instanceName;
_configure = configure;
}

internal PipelineComponent CreateComponent()
{
var builder = CreateBuilder();
var telemetry = new ResilienceStrategyTelemetry(
new ResilienceTelemetrySource(_builderName, _instanceName, null),
builder.Listener);

var initialPipeline = builder.ComponentFactory();

if (builder.ReloadTokenProducer is null)
{
return initialPipeline;
}

return PipelineComponentFactory.CreateReloadable(
initialPipeline,
builder.ReloadTokenProducer(),
() => CreateBuilder().ComponentFactory(),
telemetry);
}

private Builder CreateBuilder()
{
var context = new ConfigureBuilderContext<TKey>(_key, _builderName, _instanceName);
var builder = _activator();
builder.Name = _builderName;
builder.InstanceName = _instanceName;
_configure(builder, context);

return new(
builder.BuildPipelineComponent,
context.ReloadTokenProducer,
builder.TelemetryListener);
}

private record Builder(
Func<PipelineComponent> ComponentFactory,
Func<Func<CancellationToken>>? ReloadTokenProducer,
TelemetryListener? Listener);
}
12 changes: 8 additions & 4 deletions src/Polly.Core/Registry/ResiliencePipelineRegistry.TResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ public ResiliencePipeline<TResult> GetOrAdd(TKey key, Action<ResiliencePipelineB
{
var context = new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _instanceNameFormatter?.Invoke(key));

return _pipelines.GetOrAdd(key, static (_, factory) =>
return _pipelines.GetOrAdd(key, k =>
{
var component = CreatePipelineComponent(factory.instance._activator, factory.context, factory.configure);
var component = new RegistryPipelineComponentBuilder<ResiliencePipelineBuilder<TResult>, TKey>(
_activator,
k,
_builderNameFormatter(k),
_instanceNameFormatter?.Invoke(k),
configure).CreateComponent();
return new ResiliencePipeline<TResult>(component, DisposeBehavior.Reject);
},
(instance: this, context, configure));
});
}

public bool TryAddBuilder(TKey key, Action<ResiliencePipelineBuilder<TResult>, ConfigureBuilderContext<TKey>> configure) => _builders.TryAdd(key, configure);
Expand Down
45 changes: 8 additions & 37 deletions src/Polly.Core/Registry/ResiliencePipelineRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Polly.Telemetry;
using Polly.Utils.Pipeline;

namespace Polly.Registry;
Expand Down Expand Up @@ -124,15 +123,17 @@ public ResiliencePipeline GetOrAddPipeline(TKey key, Action<ResiliencePipelineBu
return pipeline;
}

var context = new ConfigureBuilderContext<TKey>(key, _builderNameFormatter(key), _instanceNameFormatter?.Invoke(key));

return _pipelines.GetOrAdd(key, static (_, factory) =>
return _pipelines.GetOrAdd(key, k =>
{
var component = CreatePipelineComponent(factory.instance._activator, factory.context, factory.configure);
var component = new RegistryPipelineComponentBuilder<ResiliencePipelineBuilder, TKey>(
_activator,
k,
_builderNameFormatter(k),
_instanceNameFormatter?.Invoke(k),
configure).CreateComponent();
return new ResiliencePipeline(component, DisposeBehavior.Reject);
},
(instance: this, context, configure));
});
}

/// <summary>
Expand Down Expand Up @@ -260,36 +261,6 @@ public async ValueTask DisposeAsync()
}
}

private static PipelineComponent CreatePipelineComponent<TBuilder>(
Func<TBuilder> activator,
ConfigureBuilderContext<TKey> context,
Action<TBuilder, ConfigureBuilderContext<TKey>> configure)
where TBuilder : ResiliencePipelineBuilderBase
{
Func<TBuilder> factory = () =>
{
var builder = activator();
builder.Name = context.BuilderName;
builder.InstanceName = context.BuilderInstanceName;
configure(builder, context);
return builder;
};

var builder = factory();
var pipeline = builder.BuildPipelineComponent();
var telemetry = new ResilienceStrategyTelemetry(
new ResilienceTelemetrySource(context.BuilderName, context.BuilderInstanceName, null),
builder.TelemetryListener);

if (context.ReloadTokenProducer is null)
{
return pipeline;
}

return PipelineComponentFactory.CreateReloadable(pipeline, context.ReloadTokenProducer(), () => factory().BuildPipelineComponent(), telemetry);
}

private GenericRegistry<TResult> GetGenericRegistry<TResult>()
{
if (_genericRegistry.TryGetValue(typeof(TResult), out var genericRegistry))
Expand Down

0 comments on commit 32a3390

Please sign in to comment.