Skip to content

Commit

Permalink
Prepare for .NET 8
Browse files Browse the repository at this point in the history
Backport various changes from App-vNext#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
1 parent 67d72b0 commit bb42728
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 154 deletions.
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="2.2.0" />
<PackageVersion Update="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="2.2.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
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)
{
// 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

0 comments on commit bb42728

Please sign in to comment.