Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Prepare for .NET 8
Backport various changes from #1144:
- Simplify NuGet package version management.
- Simplify TimeProviderExtensions.
- Enable .NET analyzers.
- Remove `MockTimeProvider`.
- Minor code formatting clean-ups.
  • Loading branch information
martincostello committed Jun 27, 2023
commit fd233584e2b497e6d7af5db6608e2e2d284d0ffb
33 changes: 16 additions & 17 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<PropertyGroup>
<MicrosoftExtensionsVersion>7.0.0</MicrosoftExtensionsVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<PollyVersion>8.0.0-alpha.4</PollyVersion>
</PropertyGroup>
Expand All @@ -8,13 +9,15 @@
<PackageVersion Include="BenchmarkDotNet" Version="0.13.5" />
<PackageVersion Include="FluentAssertions" Version="6.11.0" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.2" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<PackageVersion Include="MinVer" Version="4.3.0" />
Expand All @@ -27,23 +30,19 @@
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.4.0.72892" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.507" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="4.5.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="7.0.0" />
<PackageVersion Include="System.Threading.RateLimiting" Version="7.0.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="System.Threading.RateLimiting" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
<PackageVersion Include="xunit" Version="2.4.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework) == 'net7.0'">
<PackageVersion Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework) == 'net6.0'">
<PackageVersion Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
<PackageVersion Update="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'netcoreapp3.1'))">
<PackageVersion Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
<PackageVersion Update="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0</TargetFrameworks>
<RootNamespace>Polly</RootNamespace>
<ImplicitUsings>true</ImplicitUsings>
<ProjectType>Benchmark</ProjectType>
<Nullable>enable</Nullable>
Expand Down
1 change: 1 addition & 0 deletions eng/Analyzers.targets
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest</AnalysisLevel>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>
</Project>
4 changes: 1 addition & 3 deletions src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using Polly.Telemetry;

namespace Polly.Timeout;
Expand All @@ -23,7 +22,6 @@ public TimeoutResilienceStrategy(TimeoutStrategyOptions options, TimeProvider ti

public Func<OnTimeoutArguments, ValueTask>? OnTimeout { get; }

[ExcludeFromCodeCoverage]
protected internal override async ValueTask<Outcome<TResult>> ExecuteCoreAsync<TResult, TState>(
Func<ResilienceContext, TState, ValueTask<Outcome<TResult>>> callback,
ResilienceContext context,
Expand All @@ -50,7 +48,7 @@ protected internal override async ValueTask<Outcome<TResult>> ExecuteCoreAsync<T
var outcome = await ExecuteCallbackSafeAsync(callback, context, state).ConfigureAwait(context.ContinueOnCapturedContext);
var isCancellationRequested = cancellationSource.IsCancellationRequested;

// execution is finished, cleanup
// execution is finished, clean up
context.CancellationToken = previousToken;
#pragma warning disable CA1849 // Call async methods when in an async method, OK here as the callback is synchronous
registration.Dispose();
Expand Down
28 changes: 5 additions & 23 deletions src/Polly.Core/Utils/TimeProviderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,15 @@ public static Task DelayAsync(this TimeProvider timeProvider, TimeSpan delay, Re

context.CancellationToken.ThrowIfCancellationRequested();

if (context.IsSynchronous && timeProvider == TimeProvider.System)
if (context.IsSynchronous)
{
// Stryker disable once boolean : no means to test this
if (context.CancellationToken.CanBeCanceled)
{
context.CancellationToken.WaitHandle.WaitOne(delay);
context.CancellationToken.ThrowIfCancellationRequested();
}
else
{
Thread.Sleep(delay);
}

return Task.CompletedTask;
}
else
{
if (context.IsSynchronous)
{
#pragma warning disable CA1849 // For synchronous scenarios we want to return completed task
Comment thread
martintmk marked this conversation as resolved.
Outdated
timeProvider.Delay(delay, context.CancellationToken).GetAwaiter().GetResult();
timeProvider.Delay(delay, context.CancellationToken).GetAwaiter().GetResult();
#pragma warning restore CA1849

return Task.CompletedTask;
}

return timeProvider.Delay(delay, context.CancellationToken);
return Task.CompletedTask;
}

return timeProvider.Delay(delay, context.CancellationToken);
}
}
3 changes: 2 additions & 1 deletion src/Polly.Extensions/Polly.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
</ItemGroup>

<ItemGroup>
<Using Remove="System.Net.Http" />
<InternalsVisibleToTest Include="Polly.Extensions.Tests" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Polly.Core\Polly.Core.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
Expand Down
2 changes: 1 addition & 1 deletion src/Polly.RateLimiting/Polly.RateLimiting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<MutationScore>100</MutationScore>
<LegacySupport>true</LegacySupport>
</PropertyGroup>

<ItemGroup>
<Using Include="Polly.Utils" />
<Compile Include="..\Polly.Core\Utils\ExceptionUtilities.cs" Link="utils\ExceptionUtilities.cs" />
Expand Down
52 changes: 0 additions & 52 deletions test/Polly.Core.Tests/Helpers/MockTimeProvider.cs

This file was deleted.

2 changes: 1 addition & 1 deletion test/Polly.Core.Tests/Polly.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</ItemGroup>

<ItemGroup>
<Using Include="Polly.TestUtils" />
<Using Include="Polly.Core.Tests.Helpers" />
<Using Include="Polly.TestUtils" />
</ItemGroup>
</Project>
75 changes: 56 additions & 19 deletions test/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using FluentAssertions.Execution;
using Microsoft.Extensions.Time.Testing;
using Moq;
using Polly.Retry;
Expand Down Expand Up @@ -158,40 +159,76 @@ public void Retry_Infinite_Respected()
[Fact]
public async Task RetryDelayGenerator_Respected()
{
int calls = 0;
_options.OnRetry = _ => { calls++; return default; };
int retries = 0;
int generatedValues = 0;

var delay = TimeSpan.FromMilliseconds(120);
var provider = TimeProvider.System;

_options.ShouldHandle = _ => PredicateResult.True;
_options.RetryCount = 3;
_options.BackoffType = RetryBackoffType.Constant;
_options.RetryDelayGenerator = _ => new ValueTask<TimeSpan>(TimeSpan.FromMilliseconds(123));
var provider = new MockTimeProvider();
provider.SetupCreateTimer(TimeSpan.FromMilliseconds(123));
provider.Setup(p => p.GetTimestamp()).Returns(0);
provider.Setup(p => p.TimestampFrequency).Returns(10000);

var sut = CreateSut(provider.Object);
_options.OnRetry = _ =>
{
retries++;
return default;
};
_options.RetryDelayGenerator = _ =>
{
generatedValues++;
return new ValueTask<TimeSpan>(delay);
};

var before = provider.GetUtcNow();

var sut = CreateSut(provider);
await sut.ExecuteAsync(_ => default);

provider.VerifyAll();
retries.Should().Be(3);
generatedValues.Should().Be(3);

var after = provider.GetUtcNow();
(after - before).Should().BeGreaterThanOrEqualTo(delay.Add(delay).Add(delay));
}

[Fact]
public async Task RetryDelayGenerator_ZeroDelay_NoTimeProviderCalls()
{
int calls = 0;
_options.OnRetry = _ => { calls++; return default; };
int retries = 0;
int generatedValues = 0;

var delay = TimeSpan.Zero;
var provider = new ThrowingFakeTimeProvider();

_options.ShouldHandle = _ => PredicateResult.True;
_options.RetryCount = 1;
_options.RetryDelayGenerator = _ => new ValueTask<TimeSpan>(TimeSpan.FromMilliseconds(0));
var provider = new MockTimeProvider();
provider.Setup(p => p.GetTimestamp()).Returns(0);
provider.Setup(p => p.TimestampFrequency).Returns(10000);
_options.RetryCount = 3;
_options.BackoffType = RetryBackoffType.Constant;

var sut = CreateSut(provider.Object);
_options.OnRetry = _ =>
{
retries++;
return default;
};
_options.RetryDelayGenerator = _ =>
{
generatedValues++;
return new ValueTask<TimeSpan>(delay);
};

var sut = CreateSut(provider);
await sut.ExecuteAsync(_ => default);

provider.VerifyAll();
provider.VerifyNoOtherCalls();
retries.Should().Be(3);
generatedValues.Should().Be(3);
}

private sealed class ThrowingFakeTimeProvider : FakeTimeProvider
{
public override DateTimeOffset GetUtcNow() => throw new AssertionFailedException("TimeProvider should not be used.");

public override ITimer CreateTimer(TimerCallback callback, object? state, TimeSpan dueTime, TimeSpan period)
=> throw new AssertionFailedException("TimeProvider should not be used.");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ await sut.ExecuteAsync(async token =>
},
cts.Token);
}
catch (OperationCanceledException)
catch (TaskCanceledException)
Comment thread
martincostello marked this conversation as resolved.
Outdated
{
// ok
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public void RentReturn_Reusable_EnsureProperBehavior(object timeProvider)
pool.Return(cts);

var cts2 = pool.Get(System.Threading.Timeout.InfiniteTimeSpan);

#if NET6_0_OR_GREATER
if (timeProvider == TimeProvider.System)
{
Expand Down
Loading