Skip to content

Commit

Permalink
Refine integreation of TimeProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored and martincostello committed Nov 14, 2023
1 parent e8f5370 commit 38f715b
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/Polly.Core/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ Polly.CircuitBreaker.BreakDurationGeneratorArguments.FailureCount.get -> int
Polly.CircuitBreaker.BreakDurationGeneratorArguments.FailureRate.get -> double
Polly.CircuitBreaker.CircuitBreakerStrategyOptions<TResult>.BreakDurationGenerator.get -> System.Func<Polly.CircuitBreaker.BreakDurationGeneratorArguments, System.Threading.Tasks.ValueTask<System.TimeSpan>>?
Polly.CircuitBreaker.CircuitBreakerStrategyOptions<TResult>.BreakDurationGenerator.set -> void
Polly.ResiliencePipelineBuilderBase.TimeProvider.get -> System.TimeProvider!
Polly.ResiliencePipelineBuilderBase.TimeProvider.get -> System.TimeProvider?
Polly.ResiliencePipelineBuilderBase.TimeProvider.set -> void
Polly.StrategyBuilderContext.TimeProvider.get -> System.TimeProvider!
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private Builder CreateBuilder()
builder.InstanceName = _instanceName;
_configure(builder, context);

var timeProvider = builder.TimeProvider;
var timeProvider = builder.TimeProviderInternal;
var telemetry = new ResilienceStrategyTelemetry(
new ResilienceTelemetrySource(builder.Name, builder.InstanceName, null),
builder.TelemetryListener);
Expand Down
11 changes: 6 additions & 5 deletions src/Polly.Core/ResiliencePipelineBuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,9 @@ private protected ResiliencePipelineBuilderBase(ResiliencePipelineBuilderBase ot
/// Gets or sets a <see cref="TimeProvider"/> that is used by strategies that work with time.
/// </summary>
/// <value>
/// The default value is <see cref="TimeProvider.System"/>.
/// The default value is <see langword="null"/> and unless set, the <see cref="TimeProvider.System"/> will be used.
/// </value>
[Required]
public TimeProvider TimeProvider { get; set; } = TimeProvider.System;
public TimeProvider? TimeProvider { get; set; }

/// <summary>
/// Gets or sets the <see cref="Polly.Telemetry.TelemetryListener"/> that is used by Polly to report resilience events.
Expand All @@ -88,6 +87,8 @@ private protected ResiliencePipelineBuilderBase(ResiliencePipelineBuilderBase ot
[EditorBrowsable(EditorBrowsableState.Never)]
public TelemetryListener? TelemetryListener { get; set; }

internal TimeProvider TimeProviderInternal => TimeProvider ?? TimeProvider.System;

/// <summary>
/// Gets the validator that is used for the validation.
/// </summary>
Expand Down Expand Up @@ -129,13 +130,13 @@ internal PipelineComponent BuildPipelineComponent()

var source = new ResilienceTelemetrySource(Name, InstanceName, null);

return PipelineComponentFactory.CreateComposite(components, new ResilienceStrategyTelemetry(source, TelemetryListener), TimeProvider);
return PipelineComponentFactory.CreateComposite(components, new ResilienceStrategyTelemetry(source, TelemetryListener), TimeProviderInternal);
}

private PipelineComponent CreateComponent(Entry entry)
{
var source = new ResilienceTelemetrySource(Name, InstanceName, entry.Options.Name);
var context = new StrategyBuilderContext(new ResilienceStrategyTelemetry(source, TelemetryListener), TimeProvider);
var context = new StrategyBuilderContext(new ResilienceStrategyTelemetry(source, TelemetryListener), TimeProviderInternal);

var strategy = entry.Factory(context);
strategy.Options = entry.Options;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ private static void AddResiliencePipelineBuilder(this IServiceCollection service
{
var builder = new ResiliencePipelineBuilder();
builder.ConfigureTelemetry(serviceProvider.GetRequiredService<IOptions<TelemetryOptions>>().Value);
if (serviceProvider.GetService<TimeProvider>() is { } timeProvider)
{
builder.TimeProvider = timeProvider;
}
return builder;
});
}
Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Testing/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
#nullable enable
Polly.TestingResiliencePipelineBuilderExtensions
static Polly.TestingResiliencePipelineBuilderExtensions.WithTimeProvider<TBuilder>(this TBuilder! builder, System.TimeProvider! timeProvider) -> TBuilder!
26 changes: 0 additions & 26 deletions src/Polly.Testing/TestingResiliencePipelineBuilderExtensions.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class GenericResiliencePipelineBuilderTests
public void Ctor_EnsureDefaults()
{
_builder.Name.Should().BeNull();
_builder.TimeProvider.Should().Be(TimeProvider.System);
_builder.TimeProvider.Should().BeNull();
}

[Fact]
Expand Down
14 changes: 13 additions & 1 deletion test/Polly.Core.Tests/ResiliencePipelineBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ public void Ctor_EnsureDefaults()
var builder = new ResiliencePipelineBuilder();

builder.Name.Should().BeNull();
builder.TimeProvider.Should().Be(TimeProvider.System);
builder.TimeProvider.Should().BeNull();
}

[Fact]
public void TimeProviderInternal_Ok()
{
var builder = new ResiliencePipelineBuilder();
builder.TimeProviderInternal.Should().Be(TimeProvider.System);

var timeProvider = Substitute.For<TimeProvider>();
builder.TimeProvider = timeProvider;

builder.TimeProvider.Should().Be(timeProvider);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Globalization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using NSubstitute;
using Polly.DependencyInjection;
using Polly.Registry;
using Polly.Telemetry;
Expand All @@ -14,7 +16,7 @@ public class PollyServiceCollectionExtensionTests
private const string Key = "my-pipeline";
private ServiceCollection _services;

public PollyServiceCollectionExtensionTests() => _services = new ServiceCollection();
public PollyServiceCollectionExtensionTests() => _services = [];

[Fact]
public void AddResiliencePipeline_ArgValidation()
Expand All @@ -23,7 +25,7 @@ public void AddResiliencePipeline_ArgValidation()
Assert.Throws<ArgumentNullException>(() => AddResiliencePipeline(Key));
Assert.Throws<ArgumentNullException>(() => AddResiliencePipeline<string>(Key));

_services = new ServiceCollection();
_services = [];
Assert.Throws<ArgumentNullException>(() => _services.AddResiliencePipeline(
Key,
(Action<ResiliencePipelineBuilder, AddResiliencePipelineContext<string>>)null!));
Expand Down Expand Up @@ -250,6 +252,37 @@ public void AddResiliencePipeline_Multiple_Ok()
.HaveCount(30);
}

[InlineData(true)]
[InlineData(false)]
[Theory]
public void AddResiliencePipeline_EnsureTimeProvider(bool timeProviderRegistered)
{
var timeProvider = Substitute.For<TimeProvider>();
var asserted = false;

if (timeProviderRegistered)
{
_services.TryAddSingleton(timeProvider);
}

_services.AddResiliencePipeline("dummy", builder =>
{
if (timeProviderRegistered)
{
builder.TimeProvider.Should().Be(timeProvider);
}
else
{
builder.TimeProvider.Should().BeNull();
}
asserted = true;
});

CreateProvider().GetPipeline("dummy");
asserted.Should().BeTrue();
}

[Fact]
public void AddResiliencePipelineRegistry_Ok()
{
Expand Down

This file was deleted.

0 comments on commit 38f715b

Please sign in to comment.