diff --git a/docs/strategies/timeout.md b/docs/strategies/timeout.md index 54897c4486a..69ca3311836 100644 --- a/docs/strategies/timeout.md +++ b/docs/strategies/timeout.md @@ -117,8 +117,11 @@ catch (TimeoutRejectedException) | `TimeoutGenerator` | `null` | This delegate allows you to **dynamically** calculate the timeout period by utilizing information that is only available at runtime. | | `OnTimeout` | `null` | If provided then it will be invoked after the timeout occurred. | -> [!NOTE] -> If both `Timeout` and `TimeoutGenerator` are specified then `Timeout` will be ignored. +### Timeout duration calculation + +- If `TimeoutGenerator` is not specified then `Timeout` will be used. +- If both `Timeout` and `TimeoutGenerator` are specified then `Timeout` will be ignored. +- If `TimeoutGenerator` returns a `TimeSpan` that is less than or equal to `TimeSpan.Zero` then the strategy will have no effect. ### `OnTimeout` versus catching `TimeoutRejectedException` diff --git a/src/Polly.Core/Timeout/TimeoutStrategyOptions.cs b/src/Polly.Core/Timeout/TimeoutStrategyOptions.cs index 58a179a4d83..ac2fe9924ef 100644 --- a/src/Polly.Core/Timeout/TimeoutStrategyOptions.cs +++ b/src/Polly.Core/Timeout/TimeoutStrategyOptions.cs @@ -27,8 +27,9 @@ public class TimeoutStrategyOptions : ResilienceStrategyOptions /// Gets or sets a timeout generator that generates the timeout for a given execution. /// /// - /// If generator returns a value that is less or equal to - /// its value is ignored and is used instead. When generator is the is used. + /// When generator is then the property's value is used instead. + /// When generator returns a value that is less than or equal to + /// then the strategy will do nothing. /// /// Return to disable the timeout for the given execution. /// diff --git a/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs b/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs index 7a371f5931b..1af944ab350 100644 --- a/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs +++ b/test/Polly.Core.Tests/Timeout/TimeoutResilienceStrategyTests.cs @@ -117,6 +117,36 @@ await sut .WithMessage("The operation didn't complete within the allowed timeout of '00:00:02'."); } + [Fact] + public async Task Execute_TimeoutGeneratorIsNull_FallsBackToTimeout() + { + var called = false; + var timeout = TimeSpan.FromMilliseconds(10); + _options.TimeoutGenerator = null; + _options.Timeout = timeout; + + _options.OnTimeout = args => + { + called = true; + args.Timeout.Should().Be(timeout); + return default; + }; + + var sut = CreateSut(); + await sut + .Invoking(s => s.ExecuteAsync(async token => + { + var delay = _timeProvider.Delay(TimeSpan.FromMilliseconds(50), token); + _timeProvider.Advance(timeout); + await delay; + }, + CancellationToken.None) + .AsTask()) + .Should().ThrowAsync(); + + called.Should().BeTrue(); + } + [Fact] public async Task Execute_Timeout_EnsureStackTrace() {