diff --git a/test/Polly.Specs/Helpers/Bulkhead/TraceableAction.cs b/test/Polly.Specs/Helpers/Bulkhead/TraceableAction.cs index 4300bd4a6df..fb12e83c9fa 100644 --- a/test/Polly.Specs/Helpers/Bulkhead/TraceableAction.cs +++ b/test/Polly.Specs/Helpers/Bulkhead/TraceableAction.cs @@ -51,7 +51,10 @@ public Task ExecuteOnBulkhead(BulkheadPolicy bulkhead) => return default; }, _cancellationSource.Token)); - // Note re TaskCreationOptions.LongRunning: Testing the parallelization of the bulkhead policy efficiently requires the ability to start large numbers of parallel tasks in a short space of time. The ThreadPool's algorithm of only injecting extra threads (when necessary) at a rate of two-per-second however makes high-volume tests using the ThreadPool both slow and flaky. For PCL tests further, ThreadPool.SetMinThreads(...) is not available, to mitigate this. Using TaskCreationOptions.LongRunning allows us to force tasks to be started near-instantly on non-ThreadPool threads. + // Note re TaskCreationOptions.LongRunning: Testing the parallelization of the bulkhead policy efficiently requires the ability to start large numbers of parallel tasks in a short space of time. + // The ThreadPool's algorithm of only injecting extra threads (when necessary) at a rate of two-per-second however makes high-volume tests using the ThreadPool both slow and flaky. + // For PCL tests further, ThreadPool.SetMinThreads(...) is not available, to mitigate this. + // Using TaskCreationOptions.LongRunning allows us to force tasks to be started near-instantly on non-ThreadPool threads. private Task ExecuteThroughSyncBulkheadOuter(Action executeThroughBulkheadInner) { if (Status != TraceableActionStatus.Unstarted) diff --git a/test/Polly.Specs/Polly.Specs.csproj b/test/Polly.Specs/Polly.Specs.csproj index 41e5e642378..1c8581a15bf 100644 --- a/test/Polly.Specs/Polly.Specs.csproj +++ b/test/Polly.Specs/Polly.Specs.csproj @@ -9,7 +9,7 @@ [Polly]* true $(NoWarn);CA1030;CA1031;CA2008;CA2201 - $(NoWarn);S103;S104;S2184;S6966 + $(NoWarn);S104;S2184;S6966 $(NoWarn);SA1204;SA1402;SA1600 diff --git a/test/Polly.Specs/Retry/RetryAsyncSpecs.cs b/test/Polly.Specs/Retry/RetryAsyncSpecs.cs index 486c6a23700..9f95c31f0d1 100644 --- a/test/Polly.Specs/Retry/RetryAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/RetryAsyncSpecs.cs @@ -371,7 +371,8 @@ await policy.Awaiting(x => x.RaiseExceptionAsync()) public async Task Should_wait_asynchronously_for_async_onretry_delegate() { // This test relates to https://github.com/App-vNext/Polly/issues/107. - // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. However, if it compiles to async void (assigning to Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ + // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. + // However, if it compiles to async void (assigning to Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ // If Polly were to declare only an Action<...> delegate for onRetry - but users declared async () => { } onRetry delegates - the compiler would happily assign them to the Action<...>, but the next 'try' of the retry policy would/could occur before onRetry execution had completed. // This test ensures the relevant retry policy does have a Func<..., Task> form for onRetry, and that it is awaited before the next try commences. diff --git a/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs b/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs index 61b58d34489..2013ba6f21e 100644 --- a/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs @@ -240,7 +240,8 @@ await policy.Awaiting(x => x.RaiseExceptionAsync()) public async Task Should_wait_asynchronously_for_async_onretry_delegate() { // This test relates to https://github.com/App-vNext/Polly/issues/107. - // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ + // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. + // However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ // If Polly were to declare only an Action<...> delegate for onRetry - but users declared async () => { } onRetry delegates - the compiler would happily assign them to the Action<...>, but the next 'try' would/could occur before onRetry execution had completed. // This test ensures the relevant retry policy does have a Func<..., Task> form for onRetry, and that it is awaited before the next try commences. diff --git a/test/Polly.Specs/Retry/RetryTResultSpecsAsync.cs b/test/Polly.Specs/Retry/RetryTResultSpecsAsync.cs index 3e99f5c5467..9ebeb0948a2 100644 --- a/test/Polly.Specs/Retry/RetryTResultSpecsAsync.cs +++ b/test/Polly.Specs/Retry/RetryTResultSpecsAsync.cs @@ -407,7 +407,8 @@ public async Task Should_not_call_onretry_when_retry_count_is_zero_with_context( public async Task Should_wait_asynchronously_for_async_onretry_delegate() { // This test relates to https://github.com/App-vNext/Polly/issues/107. - // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ + // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. + // However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ // If Polly were to declare only an Action<...> delegate for onRetry - but users declared async () => { } onRetry delegates - the compiler would happily assign them to the Action<...>, but the next 'try' would/could occur before onRetry execution had completed. // This test ensures the relevant retry policy does have a Func<..., Task> form for onRetry, and that it is awaited before the next try commences. diff --git a/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs b/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs index 866675b3dc8..1f06fcaa2ca 100644 --- a/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs @@ -708,7 +708,8 @@ await policy.Awaiting(x => x.RaiseExceptionAsync()) public async Task Should_wait_asynchronously_for_async_onretry_delegate() { // This test relates to https://github.com/App-vNext/Polly/issues/107. - // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ + // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. + // However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ // If Polly were to declare only an Action<...> delegate for onRetry - but users declared async () => { } onRetry delegates - the compiler would happily assign them to the Action<...>, but the next 'try' would/could occur before onRetry execution had completed. // This test ensures the relevant retry policy does have a Func<..., Task> form for onRetry, and that it is awaited before the next try commences. diff --git a/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs b/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs index 041e20b1625..e18853fec86 100644 --- a/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs @@ -432,7 +432,8 @@ await policy.ExecuteAsync(async (context, _) => public async Task Should_wait_asynchronously_for_async_onretry_delegate() { // This test relates to https://github.com/App-vNext/Polly/issues/107. - // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ + // An async (...) => { ... } anonymous delegate with no return type may compile to either an async void or an async Task method; which assign to an Action<...> or Func<..., Task> respectively. + // However, if it compiles to async void (assigning tp Action<...>), then the delegate, when run, will return at the first await, and execution continues without waiting for the Action to complete, as described by Stephen Toub: https://devblogs.microsoft.com/pfxteam/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/ // If Polly were to declare only an Action<...> delegate for onRetry - but users declared async () => { } onRetry delegates - the compiler would happily assign them to the Action<...>, but the next 'try' would/could occur before onRetry execution had completed. // This test ensures the relevant retry policy does have a Func<..., Task> form for onRetry, and that it is awaited before the next try commences.