From 520ee38ce6d199c3dfc75c87188a0857880edc94 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Tue, 12 Nov 2024 20:06:24 +0000 Subject: [PATCH] Update to .NET 9 SDK (#2003) - Build with the .NET 9 SDK. - Add tests TFM for `net9.0`. - Remove tests for `net6.0` TFM. - Run workflows on PRs to `dotnet-vnext` branch. - Only audit direct NuGet dependencies. - Fix IDE0022 warning. - Temporarily disable some tests that are failing in GitHub Actions. - Add usage of `[DebuggerDisableUserUnhandledExceptions]` to avoid newer versions of the Visual Studio debugger for breaking for exceptions on async code paths we are intentionally handling. - Bump version to 8.5.0. --- .github/workflows/actions-lint.yml | 9 ++++++-- .github/workflows/build.yml | 9 ++++++-- .github/workflows/dependency-review.yml | 5 ++++- .github/workflows/gh-pages.yml | 12 +++++++++-- .github/workflows/on-push-do-docs.yml | 2 +- .github/workflows/updater-approve.yml | 5 ++++- Directory.Packages.props | 5 +++++ .../Polly.Benchmarks/Polly.Benchmarks.csproj | 2 +- .../Polly.Core.Benchmarks.csproj | 2 +- bench/benchmarks.ps1 | 2 +- eng/Common.targets | 5 +++-- eng/Library.targets | 2 +- global.json | 2 +- samples/Chaos/Chaos.csproj | 3 ++- .../DependencyInjection.csproj | 3 ++- samples/Extensibility/Extensibility.csproj | 2 +- .../GenericPipelines/GenericPipelines.csproj | 2 +- samples/Intro/Intro.csproj | 2 +- samples/Retries/Retries.csproj | 2 +- .../Hedging/Controller/TaskExecution.cs | 2 ++ src/Polly.Core/Outcome.TResult.cs | 1 - src/Polly.Core/Polly.Core.csproj | 4 ++++ src/Polly.Core/ResilienceContext.cs | 2 ++ src/Polly.Core/ResiliencePipeline.Async.cs | 8 +++---- src/Polly.Core/ResiliencePipeline.AsyncT.cs | 8 +++---- src/Polly.Core/ResiliencePipeline.Sync.cs | 12 +++++------ src/Polly.Core/ResiliencePipeline.SyncT.cs | 12 +++++------ src/Polly.Core/Retry/RetryHelper.cs | 2 ++ .../Retry/RetryResilienceStrategy.cs | 2 ++ src/Polly.Core/Utils/StrategyHelper.cs | 2 ++ src/Polly.Core/Utils/TaskHelper.cs | 1 + src/Polly/Caching/AsyncCacheEngine.cs | 1 + src/Polly/Caching/CacheEngine.cs | 1 + .../AsyncCircuitBreakerEngine.cs | 1 + .../CircuitBreaker/CircuitBreakerEngine.cs | 1 + src/Polly/Fallback/AsyncFallbackEngine.cs | 1 + src/Polly/Fallback/FallbackEngine.cs | 1 + src/Polly/Polly.csproj | 4 ++++ src/Polly/Retry/AsyncRetryEngine.cs | 1 + src/Polly/Retry/RetryEngine.cs | 1 + src/Polly/Timeout/AsyncTimeoutEngine.cs | 5 +++++ src/Polly/Timeout/TimeoutEngine.cs | 1 + ...DisableUserUnhandledExceptionsAttribute.cs | 21 +++++++++++++++++++ src/Snippets/Snippets.csproj | 2 +- test/Polly.AotTest/Polly.AotTest.csproj | 2 +- test/Polly.Core.Tests/Polly.Core.Tests.csproj | 9 ++++++-- .../Retry/RetryHelperTests.cs | 6 +----- .../Polly.Extensions.Tests.csproj | 2 +- .../Polly.RateLimiting.Tests.csproj | 2 +- test/Polly.Specs/Polly.Specs.csproj | 2 +- test/Polly.TestUtils/Polly.TestUtils.csproj | 2 +- .../Polly.Testing.Tests.csproj | 2 +- 52 files changed, 143 insertions(+), 57 deletions(-) create mode 100644 src/Shared/DebuggerDisableUserUnhandledExceptionsAttribute.cs diff --git a/.github/workflows/actions-lint.yml b/.github/workflows/actions-lint.yml index 2faa098e821..ddbe1fab250 100644 --- a/.github/workflows/actions-lint.yml +++ b/.github/workflows/actions-lint.yml @@ -2,13 +2,18 @@ name: actions-lint on: push: - branches: [ main, release/* ] + branches: + - main + - release/* paths-ignore: - '**/*.gitattributes' - '**/*.gitignore' - '**/*.md' pull_request: - branches: [ main, release/* ] + branches: + - main + - release/* + - dotnet-vnext workflow_dispatch: permissions: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3bd1ff4d8e..b3007fd55a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,10 +2,15 @@ name: build on: push: - branches: [ main, release/* ] + branches: + - main + - release/* tags: [ '*' ] pull_request: - branches: [ main, release/* ] + branches: + - main + - release/* + - dotnet-vnext workflow_dispatch: env: diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 42a0580bad1..fbcd0f20bd5 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -2,7 +2,10 @@ name: dependency-review on: pull_request: - branches: [ main, release/* ] + branches: + - main + - release/* + - dotnet-vnext permissions: contents: read diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 74f999b37f2..8fa9f853e26 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -2,9 +2,14 @@ name: github-pages on: push: - branches: [ main, release/* ] + branches: + - main + - release/* pull_request: - branches: [ main, release/* ] + branches: + - main + - release/* + - dotnet-vnext workflow_dispatch: permissions: @@ -14,6 +19,7 @@ jobs: build-docs: runs-on: ubuntu-latest + timeout-minutes: 20 steps: @@ -37,6 +43,8 @@ jobs: uses: actions/setup-dotnet@3e891b0cb619bf60e2c25674b222b8940e2c1c25 # v4.1.0 - name: Generate documentation + env: + DOTNET_ROLL_FORWARD: LatestMajor run: | dotnet tool restore dotnet build --configuration Release /p:SKIP_POLLY_ANALYZERS=true diff --git a/.github/workflows/on-push-do-docs.yml b/.github/workflows/on-push-do-docs.yml index 356d0cfc871..c254edc8108 100644 --- a/.github/workflows/on-push-do-docs.yml +++ b/.github/workflows/on-push-do-docs.yml @@ -2,7 +2,7 @@ name: on-push-do-docs on: push: - branches: [main] + branches: [ main ] paths: [ "src/Snippets/**" ] workflow_dispatch: diff --git a/.github/workflows/updater-approve.yml b/.github/workflows/updater-approve.yml index 2b6701d828e..caaca51971f 100644 --- a/.github/workflows/updater-approve.yml +++ b/.github/workflows/updater-approve.yml @@ -2,7 +2,10 @@ name: updater-approve on: pull_request: - branches: [ main, release/* ] + branches: + - main + - release/* + - dotnet-vnext permissions: contents: read diff --git a/Directory.Packages.props b/Directory.Packages.props index 8a4d7f6704d..0a4e06d16fa 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,10 @@ 8.4.2 8.0.0 + + 9.0.0 + 9.0.0 + @@ -41,6 +45,7 @@ + diff --git a/bench/Polly.Benchmarks/Polly.Benchmarks.csproj b/bench/Polly.Benchmarks/Polly.Benchmarks.csproj index c7034b11ac2..51dffa8af87 100644 --- a/bench/Polly.Benchmarks/Polly.Benchmarks.csproj +++ b/bench/Polly.Benchmarks/Polly.Benchmarks.csproj @@ -2,7 +2,7 @@ false Exe - net6.0;net8.0 + net8.0;net9.0 enable Benchmark $(NoWarn);CA1822;IDE0060 diff --git a/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj b/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj index 44cafa02f2f..8c206b165e9 100644 --- a/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj +++ b/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj @@ -1,6 +1,6 @@  - net8.0 + net9.0;net8.0 Polly true Benchmark diff --git a/bench/benchmarks.ps1 b/bench/benchmarks.ps1 index fbeec111321..4f7548d037d 100644 --- a/bench/benchmarks.ps1 +++ b/bench/benchmarks.ps1 @@ -20,6 +20,6 @@ if ($Interactive -ne $true) { $project = Join-Path "Polly.Core.Benchmarks" "Polly.Core.Benchmarks.csproj" -dotnet run --configuration $Configuration --framework net8.0 --project $project $additionalArgs +dotnet run --configuration $Configuration --framework net9.0 --project $project $additionalArgs exit $LASTEXITCODE diff --git a/eng/Common.targets b/eng/Common.targets index be35abaf9df..a1f1c4465d2 100644 --- a/eng/Common.targets +++ b/eng/Common.targets @@ -4,6 +4,7 @@ $(MSBuildThisFileDirectory)..\Polly.snk enable latest + direct true 0024000004800000940000000602000000240000525341310004000001000100150819e3494f97263a3abdd18e5e0c47b04e6c0ede44a6c51d50b545d403ceeb7cbb32d18dbbbcdd1d88a87d7b73206b126be134b0609c36aa3cb31dd2e47e393293102809b8d77f192f3188618a42e651c14ebf05f8f5b76aa91b431642b23497ed82b65d63791cdaa31d4282a2d6cbabc3fe0745b6b6690c417cabf6a1349c @@ -19,12 +20,12 @@ - 8.4 + 8.5 - $([MSBuild]::ValueOrDefault('$(MinVerMajor)', '8')).$([MSBuild]::ValueOrDefault('$(MinVerMinor)', '4')).$([MSBuild]::ValueOrDefault('$(MinVerPatch)', '0')).$(GITHUB_RUN_NUMBER) + $([MSBuild]::ValueOrDefault('$(MinVerMajor)', '8')).$([MSBuild]::ValueOrDefault('$(MinVerMinor)', '5')).$([MSBuild]::ValueOrDefault('$(MinVerPatch)', '0')).$(GITHUB_RUN_NUMBER) $(MinVerMajor).$(MinVerMinor).$(MinVerPatch)-pr.$(GITHUB_REF_NAME.Replace(`/merge`, ``)).$(GITHUB_RUN_NUMBER) diff --git a/eng/Library.targets b/eng/Library.targets index c341f4972f5..c63c339001c 100644 --- a/eng/Library.targets +++ b/eng/Library.targets @@ -14,7 +14,7 @@ true - 8.2.0 + 8.4.2 diff --git a/global.json b/global.json index 66e4c11e7c7..217f7c9fb36 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.403", + "version": "9.0.100", "allowPrerelease": false, "rollForward": "latestMajor" } diff --git a/samples/Chaos/Chaos.csproj b/samples/Chaos/Chaos.csproj index 829f96fb11b..135449de97e 100644 --- a/samples/Chaos/Chaos.csproj +++ b/samples/Chaos/Chaos.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 enable enable Chaos @@ -10,6 +10,7 @@ + diff --git a/samples/DependencyInjection/DependencyInjection.csproj b/samples/DependencyInjection/DependencyInjection.csproj index a588bb35037..7a94027a42d 100644 --- a/samples/DependencyInjection/DependencyInjection.csproj +++ b/samples/DependencyInjection/DependencyInjection.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable @@ -11,6 +11,7 @@ + diff --git a/samples/Extensibility/Extensibility.csproj b/samples/Extensibility/Extensibility.csproj index 499481d3d4e..49e230a9337 100644 --- a/samples/Extensibility/Extensibility.csproj +++ b/samples/Extensibility/Extensibility.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/samples/GenericPipelines/GenericPipelines.csproj b/samples/GenericPipelines/GenericPipelines.csproj index 0dea364499d..caa321690bb 100644 --- a/samples/GenericPipelines/GenericPipelines.csproj +++ b/samples/GenericPipelines/GenericPipelines.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/samples/Intro/Intro.csproj b/samples/Intro/Intro.csproj index 499481d3d4e..49e230a9337 100644 --- a/samples/Intro/Intro.csproj +++ b/samples/Intro/Intro.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/samples/Retries/Retries.csproj b/samples/Retries/Retries.csproj index 499481d3d4e..49e230a9337 100644 --- a/samples/Retries/Retries.csproj +++ b/samples/Retries/Retries.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/src/Polly.Core/Hedging/Controller/TaskExecution.cs b/src/Polly.Core/Hedging/Controller/TaskExecution.cs index fee82e68081..a87798351db 100644 --- a/src/Polly.Core/Hedging/Controller/TaskExecution.cs +++ b/src/Polly.Core/Hedging/Controller/TaskExecution.cs @@ -199,6 +199,7 @@ public async ValueTask ResetAsync() _stopExecutionTimestamp = 0; } + [DebuggerDisableUserUnhandledExceptions] private async Task ExecuteSecondaryActionAsync(Func>> action) { Outcome outcome; @@ -218,6 +219,7 @@ private async Task ExecuteSecondaryActionAsync(Func>> actio private async Task ExecuteCreateActionException(Exception e) => await UpdateOutcomeAsync(Polly.Outcome.FromException(e)).ConfigureAwait(Context.ContinueOnCapturedContext); + [DebuggerDisableUserUnhandledExceptions] private async Task ExecutePrimaryActionAsync(Func>> primaryCallback, TState state) { Outcome outcome; diff --git a/src/Polly.Core/Outcome.TResult.cs b/src/Polly.Core/Outcome.TResult.cs index ad5a077fce9..672451ab651 100644 --- a/src/Polly.Core/Outcome.TResult.cs +++ b/src/Polly.Core/Outcome.TResult.cs @@ -90,5 +90,4 @@ internal TResult GetResultOrRethrow() ExceptionDispatchInfo?.Throw(); return Result!; } - } diff --git a/src/Polly.Core/Polly.Core.csproj b/src/Polly.Core/Polly.Core.csproj index 87d5cf5f18d..22c5a9d396e 100644 --- a/src/Polly.Core/Polly.Core.csproj +++ b/src/Polly.Core/Polly.Core.csproj @@ -36,4 +36,8 @@ + + + + diff --git a/src/Polly.Core/ResilienceContext.cs b/src/Polly.Core/ResilienceContext.cs index d77d1d2a1cc..d20d3b03866 100644 --- a/src/Polly.Core/ResilienceContext.cs +++ b/src/Polly.Core/ResilienceContext.cs @@ -74,9 +74,11 @@ internal void InitializeFrom(ResilienceContext context, CancellationToken cancel Properties.AddOrReplaceProperties(context.Properties); } +#pragma warning disable S3236 // Remove this argument from the method call; it hides the caller information. [ExcludeFromCodeCoverage] [Conditional("DEBUG")] internal void AssertInitialized() => Debug.Assert(IsInitialized, "The resilience context is not initialized."); +#pragma warning restore S3236 // Remove this argument from the method call; it hides the caller information. internal ResilienceContext Initialize(bool isSynchronous) { diff --git a/src/Polly.Core/ResiliencePipeline.Async.cs b/src/Polly.Core/ResiliencePipeline.Async.cs index b556446d4d7..2505baebf49 100644 --- a/src/Polly.Core/ResiliencePipeline.Async.cs +++ b/src/Polly.Core/ResiliencePipeline.Async.cs @@ -25,7 +25,7 @@ public async ValueTask ExecuteAsync( InitializeAsyncContext(context); var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { @@ -60,7 +60,7 @@ public async ValueTask ExecuteAsync( InitializeAsyncContext(context); var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { @@ -99,7 +99,7 @@ public async ValueTask ExecuteAsync( try { var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { @@ -140,7 +140,7 @@ public async ValueTask ExecuteAsync( try { var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { diff --git a/src/Polly.Core/ResiliencePipeline.AsyncT.cs b/src/Polly.Core/ResiliencePipeline.AsyncT.cs index f12a7521b6c..72e9d85ce35 100644 --- a/src/Polly.Core/ResiliencePipeline.AsyncT.cs +++ b/src/Polly.Core/ResiliencePipeline.AsyncT.cs @@ -53,7 +53,7 @@ public async ValueTask ExecuteAsync( InitializeAsyncContext(context); var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { @@ -88,7 +88,7 @@ public async ValueTask ExecuteAsync( InitializeAsyncContext(context); var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { @@ -127,7 +127,7 @@ public async ValueTask ExecuteAsync( try { var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { @@ -168,7 +168,7 @@ public async ValueTask ExecuteAsync( try { var outcome = await Component.ExecuteCore( - static async (context, state) => + [DebuggerDisableUserUnhandledExceptions] static async (context, state) => { try { diff --git a/src/Polly.Core/ResiliencePipeline.Sync.cs b/src/Polly.Core/ResiliencePipeline.Sync.cs index 32cb19ad501..724276270e9 100644 --- a/src/Polly.Core/ResiliencePipeline.Sync.cs +++ b/src/Polly.Core/ResiliencePipeline.Sync.cs @@ -24,7 +24,7 @@ public void Execute( InitializeSyncContext(context); Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -56,7 +56,7 @@ public void Execute( InitializeSyncContext(context); Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -92,7 +92,7 @@ public void Execute( try { Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -130,7 +130,7 @@ public void Execute( try { Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -169,7 +169,7 @@ public void Execute( try { Component.ExecuteCoreSync( - static (_, state) => + [DebuggerDisableUserUnhandledExceptions] static (_, state) => { try { @@ -204,7 +204,7 @@ public void Execute(Action callback) try { Component.ExecuteCoreSync( - static (_, state) => + [DebuggerDisableUserUnhandledExceptions] static (_, state) => { try { diff --git a/src/Polly.Core/ResiliencePipeline.SyncT.cs b/src/Polly.Core/ResiliencePipeline.SyncT.cs index 844f42d802e..da748e56d75 100644 --- a/src/Polly.Core/ResiliencePipeline.SyncT.cs +++ b/src/Polly.Core/ResiliencePipeline.SyncT.cs @@ -26,7 +26,7 @@ public TResult Execute( InitializeSyncContext(context); return Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -60,7 +60,7 @@ public TResult Execute( InitializeSyncContext(context); return Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -95,7 +95,7 @@ public TResult Execute( try { return Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { @@ -131,7 +131,7 @@ public TResult Execute(Func callback) try { return Component.ExecuteCoreSync( - static (_, state) => + [DebuggerDisableUserUnhandledExceptions] static (_, state) => { try { @@ -169,7 +169,7 @@ public TResult Execute(Func callback, TState s try { return Component.ExecuteCoreSync( - static (_, state) => + [DebuggerDisableUserUnhandledExceptions] static (_, state) => { try { @@ -211,7 +211,7 @@ public TResult Execute( try { return Component.ExecuteCoreSync( - static (context, state) => + [DebuggerDisableUserUnhandledExceptions] static (context, state) => { try { diff --git a/src/Polly.Core/Retry/RetryHelper.cs b/src/Polly.Core/Retry/RetryHelper.cs index 1acbbf8f6cc..9736a83375c 100644 --- a/src/Polly.Core/Retry/RetryHelper.cs +++ b/src/Polly.Core/Retry/RetryHelper.cs @@ -124,7 +124,9 @@ private static TimeSpan DecorrelatedJitterBackoffV2(int attempt, TimeSpan baseDe long ticks = (long)Math.Min(formulaIntrinsicValue * RpScalingFactor * targetTicksFirstDelay, MaxTimeSpanTicks); +#pragma warning disable S3236 // Remove this argument from the method call; it hides the caller information. Debug.Assert(ticks >= 0, "ticks cannot be negative"); +#pragma warning restore S3236 // Remove this argument from the method call; it hides the caller information. return TimeSpan.FromTicks(ticks); } diff --git a/src/Polly.Core/Retry/RetryResilienceStrategy.cs b/src/Polly.Core/Retry/RetryResilienceStrategy.cs index 6402875d69b..3b378b3a5a3 100644 --- a/src/Polly.Core/Retry/RetryResilienceStrategy.cs +++ b/src/Polly.Core/Retry/RetryResilienceStrategy.cs @@ -83,7 +83,9 @@ protected internal override async ValueTask> ExecuteCore(Func } } +#pragma warning disable S3236 // Remove this argument from the method call; it hides the caller information. Debug.Assert(delay >= TimeSpan.Zero, "The delay cannot be negative."); +#pragma warning restore S3236 // Remove this argument from the method call; it hides the caller information. var onRetryArgs = new OnRetryArguments(context, outcome, attempt, delay, executionTime); _telemetry.Report, T>(new(ResilienceEventSeverity.Warning, RetryConstants.OnRetryEvent), onRetryArgs); diff --git a/src/Polly.Core/Utils/StrategyHelper.cs b/src/Polly.Core/Utils/StrategyHelper.cs index e0f1d9568a0..2b63321b079 100644 --- a/src/Polly.Core/Utils/StrategyHelper.cs +++ b/src/Polly.Core/Utils/StrategyHelper.cs @@ -4,6 +4,7 @@ internal static class StrategyHelper { + [DebuggerDisableUserUnhandledExceptions] public static ValueTask> ExecuteCallbackSafeAsync( Func>> callback, ResilienceContext context, @@ -29,6 +30,7 @@ public static ValueTask> ExecuteCallbackSafeAsync>(Outcome.FromException(e)); } + [DebuggerDisableUserUnhandledExceptions] static async ValueTask> AwaitTask(ValueTask> task, bool continueOnCapturedContext) { try diff --git a/src/Polly.Core/Utils/TaskHelper.cs b/src/Polly.Core/Utils/TaskHelper.cs index cd998dea2b7..d874af21aba 100644 --- a/src/Polly.Core/Utils/TaskHelper.cs +++ b/src/Polly.Core/Utils/TaskHelper.cs @@ -1,5 +1,6 @@ namespace Polly.Utils; +#pragma warning disable S3236 // Remove this argument from the method call; it hides the caller information. #pragma warning disable S5034 // "ValueTask" should be consumed correctly internal static class TaskHelper diff --git a/src/Polly/Caching/AsyncCacheEngine.cs b/src/Polly/Caching/AsyncCacheEngine.cs index ccf9c2b195a..fedb55fc71d 100644 --- a/src/Polly/Caching/AsyncCacheEngine.cs +++ b/src/Polly/Caching/AsyncCacheEngine.cs @@ -3,6 +3,7 @@ namespace Polly.Caching; internal static class AsyncCacheEngine { + [DebuggerDisableUserUnhandledExceptions] internal static async Task ImplementationAsync( IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, diff --git a/src/Polly/Caching/CacheEngine.cs b/src/Polly/Caching/CacheEngine.cs index 796b3e00ab4..c89fae9c28e 100644 --- a/src/Polly/Caching/CacheEngine.cs +++ b/src/Polly/Caching/CacheEngine.cs @@ -3,6 +3,7 @@ namespace Polly.Caching; internal static class CacheEngine { + [DebuggerDisableUserUnhandledExceptions] internal static TResult Implementation( ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, diff --git a/src/Polly/CircuitBreaker/AsyncCircuitBreakerEngine.cs b/src/Polly/CircuitBreaker/AsyncCircuitBreakerEngine.cs index 1a5905fa228..bb3ec74af91 100644 --- a/src/Polly/CircuitBreaker/AsyncCircuitBreakerEngine.cs +++ b/src/Polly/CircuitBreaker/AsyncCircuitBreakerEngine.cs @@ -2,6 +2,7 @@ internal static class AsyncCircuitBreakerEngine { + [DebuggerDisableUserUnhandledExceptions] internal static async Task ImplementationAsync( Func> action, Context context, diff --git a/src/Polly/CircuitBreaker/CircuitBreakerEngine.cs b/src/Polly/CircuitBreaker/CircuitBreakerEngine.cs index ef8883aac28..c5037a4fb01 100644 --- a/src/Polly/CircuitBreaker/CircuitBreakerEngine.cs +++ b/src/Polly/CircuitBreaker/CircuitBreakerEngine.cs @@ -4,6 +4,7 @@ namespace Polly.CircuitBreaker; internal static class CircuitBreakerEngine { + [DebuggerDisableUserUnhandledExceptions] internal static TResult Implementation( Func action, Context context, diff --git a/src/Polly/Fallback/AsyncFallbackEngine.cs b/src/Polly/Fallback/AsyncFallbackEngine.cs index 79a58554b32..f2c268fe808 100644 --- a/src/Polly/Fallback/AsyncFallbackEngine.cs +++ b/src/Polly/Fallback/AsyncFallbackEngine.cs @@ -3,6 +3,7 @@ namespace Polly.Fallback; internal static class AsyncFallbackEngine { + [DebuggerDisableUserUnhandledExceptions] internal static async Task ImplementationAsync( Func> action, Context context, diff --git a/src/Polly/Fallback/FallbackEngine.cs b/src/Polly/Fallback/FallbackEngine.cs index 1193286891f..96351071a9d 100644 --- a/src/Polly/Fallback/FallbackEngine.cs +++ b/src/Polly/Fallback/FallbackEngine.cs @@ -3,6 +3,7 @@ namespace Polly.Fallback; internal static class FallbackEngine { + [DebuggerDisableUserUnhandledExceptions] internal static TResult Implementation( Func action, Context context, diff --git a/src/Polly/Polly.csproj b/src/Polly/Polly.csproj index 3a15d8cba4d..5f1742bd8b2 100644 --- a/src/Polly/Polly.csproj +++ b/src/Polly/Polly.csproj @@ -26,4 +26,8 @@ + + + + diff --git a/src/Polly/Retry/AsyncRetryEngine.cs b/src/Polly/Retry/AsyncRetryEngine.cs index 7237366b8f2..6672249b53d 100644 --- a/src/Polly/Retry/AsyncRetryEngine.cs +++ b/src/Polly/Retry/AsyncRetryEngine.cs @@ -3,6 +3,7 @@ namespace Polly.Retry; internal static class AsyncRetryEngine { + [DebuggerDisableUserUnhandledExceptions] internal static async Task ImplementationAsync( Func> action, Context context, diff --git a/src/Polly/Retry/RetryEngine.cs b/src/Polly/Retry/RetryEngine.cs index 966da9858d8..743e08711bf 100644 --- a/src/Polly/Retry/RetryEngine.cs +++ b/src/Polly/Retry/RetryEngine.cs @@ -3,6 +3,7 @@ namespace Polly.Retry; internal static class RetryEngine { + [DebuggerDisableUserUnhandledExceptions] internal static TResult Implementation( Func action, Context context, diff --git a/src/Polly/Timeout/AsyncTimeoutEngine.cs b/src/Polly/Timeout/AsyncTimeoutEngine.cs index fc008c3b4fc..dfa168fd4b1 100644 --- a/src/Polly/Timeout/AsyncTimeoutEngine.cs +++ b/src/Polly/Timeout/AsyncTimeoutEngine.cs @@ -2,6 +2,7 @@ internal static class AsyncTimeoutEngine { + [DebuggerDisableUserUnhandledExceptions] internal static async Task ImplementationAsync( Func> action, Context context, @@ -57,7 +58,11 @@ internal static async Task ImplementationAsync( // See https://github.com/App-vNext/Polly/issues/722. if (!combinedTokenSource.IsCancellationRequested && timeoutCancellationTokenSource.IsCancellationRequested) { +#if NET8_0_OR_GREATER + await combinedTokenSource.CancelAsync().ConfigureAwait(false); +#else combinedTokenSource.Cancel(); +#endif } } } diff --git a/src/Polly/Timeout/TimeoutEngine.cs b/src/Polly/Timeout/TimeoutEngine.cs index 2afbfd0685c..8b470f67dbd 100644 --- a/src/Polly/Timeout/TimeoutEngine.cs +++ b/src/Polly/Timeout/TimeoutEngine.cs @@ -4,6 +4,7 @@ namespace Polly.Timeout; internal static class TimeoutEngine { + [DebuggerDisableUserUnhandledExceptions] internal static TResult Implementation( Func action, Context context, diff --git a/src/Shared/DebuggerDisableUserUnhandledExceptionsAttribute.cs b/src/Shared/DebuggerDisableUserUnhandledExceptionsAttribute.cs new file mode 100644 index 00000000000..f14cbae0cb0 --- /dev/null +++ b/src/Shared/DebuggerDisableUserUnhandledExceptionsAttribute.cs @@ -0,0 +1,21 @@ +#pragma warning disable +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Adapted from https://github.com/dotnet/runtime/blob/bffe34e0c7ff8a05e79d884ed8447426aae17bfb/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerDisableUserUnhandledExceptionsAttribute.cs +// See the following links for more information and context: +// https://github.com/dotnet/runtime/issues/103105, +// https://github.com/dotnet/runtime/pull/104813 +// https://github.com/dotnet/aspnetcore/issues/57085 + +namespace System.Diagnostics; + +/// +/// If a .NET Debugger is attached which supports the Debugger.BreakForUserUnhandledException(Exception) API, +/// this attribute will prevent the debugger from breaking on user-unhandled exceptions when the +/// exception is caught by a method with this attribute, unless BreakForUserUnhandledException is called. +/// +[AttributeUsage(AttributeTargets.Method)] +internal sealed class DebuggerDisableUserUnhandledExceptionsAttribute : Attribute +{ +} diff --git a/src/Snippets/Snippets.csproj b/src/Snippets/Snippets.csproj index efcf28ecefb..a5432022f89 100644 --- a/src/Snippets/Snippets.csproj +++ b/src/Snippets/Snippets.csproj @@ -2,7 +2,7 @@ Library - net8.0 + net9.0 enable enable Library diff --git a/test/Polly.AotTest/Polly.AotTest.csproj b/test/Polly.AotTest/Polly.AotTest.csproj index 06c8c79c498..15fe2ed0c12 100644 --- a/test/Polly.AotTest/Polly.AotTest.csproj +++ b/test/Polly.AotTest/Polly.AotTest.csproj @@ -5,7 +5,7 @@ true true true - net8.0 + net9.0 diff --git a/test/Polly.Core.Tests/Polly.Core.Tests.csproj b/test/Polly.Core.Tests/Polly.Core.Tests.csproj index 33b7e17deba..bceada5ec70 100644 --- a/test/Polly.Core.Tests/Polly.Core.Tests.csproj +++ b/test/Polly.Core.Tests/Polly.Core.Tests.csproj @@ -1,7 +1,8 @@  - net8.0;net6.0 + net9.0;net8.0 $(TargetFrameworks);net481 + false Test enable 100 @@ -11,11 +12,15 @@ - + + + + + diff --git a/test/Polly.Core.Tests/Retry/RetryHelperTests.cs b/test/Polly.Core.Tests/Retry/RetryHelperTests.cs index 822d62dcc28..59b074dcc92 100644 --- a/test/Polly.Core.Tests/Retry/RetryHelperTests.cs +++ b/test/Polly.Core.Tests/Retry/RetryHelperTests.cs @@ -9,10 +9,8 @@ public class RetryHelperTests private Func _randomizer = new RandomUtil(0).NextDouble; public static TheoryData Attempts() - { #pragma warning disable IDE0028 -#pragma warning disable IDE0022 // Use expression body for method - return new() + => new() { 1, 2, @@ -24,9 +22,7 @@ public static TheoryData Attempts() 1_024, 1_025, }; -#pragma warning restore IDE0022 // Use expression body for method #pragma warning restore IDE0028 - } [Fact] public void IsValidDelay_Ok() diff --git a/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj b/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj index 24215514ed0..80498676560 100644 --- a/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj +++ b/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj @@ -1,6 +1,6 @@  - net8.0;net6.0 + net9.0;net8.0 $(TargetFrameworks);net481 Test enable diff --git a/test/Polly.RateLimiting.Tests/Polly.RateLimiting.Tests.csproj b/test/Polly.RateLimiting.Tests/Polly.RateLimiting.Tests.csproj index 42b1b5e4c23..23cf1166060 100644 --- a/test/Polly.RateLimiting.Tests/Polly.RateLimiting.Tests.csproj +++ b/test/Polly.RateLimiting.Tests/Polly.RateLimiting.Tests.csproj @@ -1,6 +1,6 @@  - net8.0;net6.0 + net9.0;net8.0 $(TargetFrameworks);net481 Test enable diff --git a/test/Polly.Specs/Polly.Specs.csproj b/test/Polly.Specs/Polly.Specs.csproj index cc9cc0eacf4..1b4e7b65f09 100644 --- a/test/Polly.Specs/Polly.Specs.csproj +++ b/test/Polly.Specs/Polly.Specs.csproj @@ -1,7 +1,7 @@  - net6.0;net8.0 + net8.0;net9.0 $(TargetFrameworks);net481 enable Test diff --git a/test/Polly.TestUtils/Polly.TestUtils.csproj b/test/Polly.TestUtils/Polly.TestUtils.csproj index 4572d30364d..b1a41cf4c38 100644 --- a/test/Polly.TestUtils/Polly.TestUtils.csproj +++ b/test/Polly.TestUtils/Polly.TestUtils.csproj @@ -1,6 +1,6 @@  - net8.0;net6.0 + net9.0;net8.0 $(TargetFrameworks);net481 Library enable diff --git a/test/Polly.Testing.Tests/Polly.Testing.Tests.csproj b/test/Polly.Testing.Tests/Polly.Testing.Tests.csproj index c69ecd3dc6a..5bd1053492c 100644 --- a/test/Polly.Testing.Tests/Polly.Testing.Tests.csproj +++ b/test/Polly.Testing.Tests/Polly.Testing.Tests.csproj @@ -1,6 +1,6 @@  - net8.0;net6.0 + net9.0;net8.0 $(TargetFrameworks);net481 Test enable