Skip to content

Commit

Permalink
Documenting thrown exceptions (#1188)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored May 16, 2023
1 parent de731b8 commit f4d5347
Show file tree
Hide file tree
Showing 50 changed files with 214 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public void AddTimeout_InvalidTimeout_EnsureValidated(TimeSpan timeout)
{
var builder = new ResilienceStrategyBuilder();

Assert.Throws<ArgumentOutOfRangeException>(() => builder.AddTimeout(timeout));
Assert.Throws<ArgumentOutOfRangeException>(() => builder.AddTimeout(timeout, args => { }));
Assert.Throws<ValidationException>(() => builder.AddTimeout(timeout));
Assert.Throws<ValidationException>(() => builder.AddTimeout(timeout, args => { }));
}

[MemberData(nameof(AddTimeout_Ok_Data))]
Expand Down
14 changes: 0 additions & 14 deletions src/Polly.Core.Tests/Timeout/TimeoutUtilTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,6 @@ public class TimeoutUtilTests
{ System.Threading.Timeout.InfiniteTimeSpan, true },
};

[MemberData(nameof(TimeoutTestUtils.InvalidTimeouts), MemberType = typeof(TimeoutTestUtils))]
[Theory]
public void ValidateTimeout_Invalid_Throws(TimeSpan timeSpan)
{
Assert.Throws<ArgumentOutOfRangeException>(() => TimeoutUtil.ValidateTimeout(timeSpan));
}

[MemberData(nameof(TimeoutTestUtils.ValidTimeouts), MemberType = typeof(TimeoutTestUtils))]
[Theory]
public void ValidateTimeout_Valid_DoesNotThrow(TimeSpan timeSpan)
{
this.Invoking(_ => TimeoutUtil.ValidateTimeout(timeSpan)).Should().NotThrow();
}

[MemberData(nameof(ShouldApplyTimeoutData))]
[Theory]
public void ShouldApplyTimeout_Ok(TimeSpan timeSpan, bool result)
Expand Down
10 changes: 8 additions & 2 deletions src/Polly.Core/CircuitBreaker/CircuitBreakerManualControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ internal void Initialize(Func<ResilienceContext, Task> onIsolate, Func<Resilienc
/// The initialization happens when the circuit-breaker strategy is attached to this class.
/// This happens when the final strategy is created by the <see cref="ResilienceStrategyBuilder.Build"/> call.
/// </remarks>
public bool IsInitialized => _onIsolate != null;
internal bool IsInitialized => _onIsolate != null;

/// <summary>
/// Isolates (opens) the circuit manually, and holds it in this state until a call to <see cref="CloseAsync(CancellationToken)"/> is made.
/// </summary>
/// <param name="context">The resilience context.</param>
/// <returns>The instance of <see cref="Task"/> that represents the asynchronous execution.</returns>
/// <exception cref="InvalidOperationException">Thrown if manual control is not initialized.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="context"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when manual control is not initialized.</exception>
/// <exception cref="ObjectDisposedException">Thrown when calling this method after this object is disposed.</exception>
public Task IsolateAsync(ResilienceContext context)
{
Guard.NotNull(context);
Expand All @@ -57,6 +59,7 @@ public Task IsolateAsync(ResilienceContext context)
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The instance of <see cref="Task"/> that represents the asynchronous execution.</returns>
/// <exception cref="InvalidOperationException">Thrown if manual control is not initialized.</exception>
/// <exception cref="ObjectDisposedException">Thrown when calling this method after this object is disposed.</exception>
public async Task IsolateAsync(CancellationToken cancellationToken = default)
{
var context = ResilienceContext.Get();
Expand All @@ -77,7 +80,9 @@ public async Task IsolateAsync(CancellationToken cancellationToken = default)
/// </summary>
/// <param name="context">The resilience context.</param>
/// <returns>The instance of <see cref="Task"/> that represents the asynchronous execution.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="context"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown if manual control is not initialized.</exception>
/// <exception cref="ObjectDisposedException">Thrown when calling this method after this object is disposed.</exception>
public Task CloseAsync(ResilienceContext context)
{
Guard.NotNull(context);
Expand All @@ -97,6 +102,7 @@ public Task CloseAsync(ResilienceContext context)
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The instance of <see cref="Task"/> that represents the asynchronous execution.</returns>
/// <exception cref="InvalidOperationException">Thrown if manual control is not initialized.</exception>
/// <exception cref="ObjectDisposedException">Thrown when calling this method after this object is disposed.</exception>
public async Task CloseAsync(CancellationToken cancellationToken = default)
{
var context = ResilienceContext.Get();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Polly.CircuitBreaker;
using Polly.CircuitBreaker.Health;
using Polly.Strategy;
Expand All @@ -22,6 +23,8 @@ public static class CircuitBreakerResilienceStrategyBuilderExtensions
/// If you are discarding the strategy created by this call make sure to use <see cref="CircuitBreakerManualControl"/> and dispose the manual control instance when the strategy is no longer used.
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddAdvancedCircuitBreaker<TResult>(this ResilienceStrategyBuilder builder, AdvancedCircuitBreakerStrategyOptions<TResult> options)
{
Guard.NotNull(builder);
Expand All @@ -44,6 +47,8 @@ public static ResilienceStrategyBuilder AddAdvancedCircuitBreaker<TResult>(this
/// If you are discarding the strategy created by this call make sure to use <see cref="CircuitBreakerManualControl"/> and dispose the manual control instance when the strategy is no longer used.
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddAdvancedCircuitBreaker(this ResilienceStrategyBuilder builder, AdvancedCircuitBreakerStrategyOptions options)
{
Guard.NotNull(builder);
Expand All @@ -67,6 +72,8 @@ public static ResilienceStrategyBuilder AddAdvancedCircuitBreaker(this Resilienc
/// If you are discarding the strategy created by this call make sure to use <see cref="CircuitBreakerManualControl"/> and dispose the manual control instance when the strategy is no longer used.
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddSimpleCircuitBreaker<TResult>(this ResilienceStrategyBuilder builder, SimpleCircuitBreakerStrategyOptions<TResult> options)
{
Guard.NotNull(builder);
Expand All @@ -89,6 +96,8 @@ public static ResilienceStrategyBuilder AddSimpleCircuitBreaker<TResult>(this Re
/// If you are discarding the strategy created by this call make sure to use <see cref="CircuitBreakerManualControl"/> and dispose the manual control instance when the strategy is no longer used.
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddSimpleCircuitBreaker(this ResilienceStrategyBuilder builder, SimpleCircuitBreakerStrategyOptions options)
{
Guard.NotNull(builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal void Initialize(Func<CircuitState> circuitStateProvider, Func<Outcome?>
/// The initialization happens when the circuit-breaker strategy is attached to this class.
/// This happens when the final strategy is created by the <see cref="ResilienceStrategyBuilder.Build"/> call.
/// </remarks>
public bool IsInitialized => _circuitStateProvider != null;
internal bool IsInitialized => _circuitStateProvider != null;

/// <summary>
/// Gets the state of the underlying circuit.
Expand Down
3 changes: 3 additions & 0 deletions src/Polly.Core/Fallback/FallbackHandler.TResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public sealed class FallbackHandler<TResult>
/// <summary>
/// Gets or sets the fallback action to be executed if <see cref="ShouldHandle"/> predicate evaluates as true.
/// </summary>
/// <remarks>
/// This property is required. Defaults to <see langword="null"/>.
/// </remarks>
[Required]
public Func<Outcome<TResult>, HandleFallbackArguments, ValueTask<TResult>>? FallbackAction { get; set; } = null;
}
5 changes: 5 additions & 0 deletions src/Polly.Core/Fallback/FallbackHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Polly.Strategy;

namespace Polly.Fallback;
Expand All @@ -21,6 +22,8 @@ public sealed partial class FallbackHandler
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="configure">An action that configures the fallback handler instance for a specific result.</param>
/// <returns>The current instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="configure"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when the <see cref="FallbackHandler{TResult}"/> configured by <paramref name="configure"/> is invalid.</exception>
public FallbackHandler SetFallback<TResult>(Action<FallbackHandler<TResult>> configure)
{
Guard.NotNull(configure);
Expand All @@ -46,6 +49,8 @@ public FallbackHandler SetFallback<TResult>(Action<FallbackHandler<TResult>> con
/// </summary>
/// <param name="configure">An action that configures the void-based fallback handler.</param>
/// <returns>The current instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="configure"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when the <see cref="VoidFallbackHandler"/> configured by <paramref name="configure"/> is invalid.</exception>
public FallbackHandler SetVoidFallback(Action<VoidFallbackHandler> configure)
{
Guard.NotNull(configure);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.ComponentModel.DataAnnotations;
using Polly.Fallback;
using Polly.Strategy;

Expand All @@ -17,6 +18,7 @@ public static class FallbackResilienceStrategyBuilderExtensions
/// <param name="shouldHandle">An action to configure the fallback predicate.</param>
/// <param name="fallbackAction">The fallback action to be executed.</param>
/// <returns>The builder instance with the fallback strategy added.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="shouldHandle"/> or <paramref name="fallbackAction"/> is <see langword="null"/>.</exception>
public static ResilienceStrategyBuilder AddFallback<TResult>(
this ResilienceStrategyBuilder builder,
Action<OutcomePredicate<HandleFallbackArguments, TResult>> shouldHandle,
Expand All @@ -43,6 +45,8 @@ public static ResilienceStrategyBuilder AddFallback<TResult>(
/// <param name="builder">The resilience strategy builder.</param>
/// <param name="options">The options to configure the fallback resilience strategy.</param>
/// <returns>The builder instance with the fallback strategy added.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddFallback<TResult>(this ResilienceStrategyBuilder builder, FallbackStrategyOptions<TResult> options)
{
Guard.NotNull(builder);
Expand All @@ -59,6 +63,8 @@ public static ResilienceStrategyBuilder AddFallback<TResult>(this ResilienceStra
/// <param name="builder">The resilience strategy builder.</param>
/// <param name="options">The options to configure the fallback resilience strategy.</param>
/// <returns>The builder instance with the fallback strategy added.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddFallback(this ResilienceStrategyBuilder builder, FallbackStrategyOptions options)
{
Guard.NotNull(builder);
Expand Down
3 changes: 3 additions & 0 deletions src/Polly.Core/Fallback/VoidFallbackHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public sealed class VoidFallbackHandler
/// <summary>
/// Gets or sets the fallback action to be executed when the <see cref="ShouldHandle"/> predicate evaluates as true.
/// </summary>
/// <remarks>
/// This property is required. Defaults to <see langword="null"/>.
/// </remarks>
[Required]
public Func<Outcome, HandleFallbackArguments, ValueTask>? FallbackAction { get; set; } = null;
}
5 changes: 5 additions & 0 deletions src/Polly.Core/Hedging/HedgingHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Polly.Strategy;

namespace Polly.Hedging;
Expand All @@ -21,6 +22,8 @@ public sealed partial class HedgingHandler
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="configure">An action that configures the hedging handler instance for a specific result.</param>
/// <returns>The current instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="configure"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when the <see cref="HedgingHandler{TResult}"/> configured by <paramref name="configure"/> is invalid.</exception>
public HedgingHandler SetHedging<TResult>(Action<HedgingHandler<TResult>> configure)
{
Guard.NotNull(configure);
Expand All @@ -41,6 +44,8 @@ public HedgingHandler SetHedging<TResult>(Action<HedgingHandler<TResult>> config
/// </summary>
/// <param name="configure">An action that configures the void-based hedging handler.</param>
/// <returns>The current instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="configure"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when the <see cref="VoidHedgingHandler"/> configured by <paramref name="configure"/> is invalid.</exception>
public HedgingHandler SetVoidHedging(Action<VoidHedgingHandler> configure)
{
Guard.NotNull(configure);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Polly.Hedging;

namespace Polly;
Expand All @@ -14,6 +15,8 @@ public static class HedgingResilienceStrategyBuilderExtensions
/// <param name="builder">The resilience strategy builder.</param>
/// <param name="options">The options to configure the hedging resilience strategy.</param>
/// <returns>The builder instance with the hedging strategy added.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddHedging<TResult>(this ResilienceStrategyBuilder builder, HedgingStrategyOptions<TResult> options)
{
Guard.NotNull(builder);
Expand All @@ -30,6 +33,8 @@ public static ResilienceStrategyBuilder AddHedging<TResult>(this ResilienceStrat
/// <param name="builder">The resilience strategy builder.</param>
/// <param name="options">The options to configure the hedging resilience strategy.</param>
/// <returns>The builder instance with the hedging strategy added.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
public static ResilienceStrategyBuilder AddHedging(this ResilienceStrategyBuilder builder, HedgingStrategyOptions options)
{
Guard.NotNull(builder);
Expand Down
3 changes: 3 additions & 0 deletions src/Polly.Core/Hedging/HedgingStrategyOptions.TResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class HedgingStrategyOptions<TResult> : ResilienceStrategyOptions
/// <summary>
/// Gets or sets the hedging action generator that creates hedged actions.
/// </summary>
/// <remarks>
/// This property is required. Defaults to <see langword="null"/>.
/// </remarks>
[Required]
public Func<HedgingActionGeneratorArguments<TResult>, Func<Task<TResult>>?>? HedgingActionGenerator { get; set; } = null;

Expand Down
5 changes: 5 additions & 0 deletions src/Polly.Core/Registry/ResilienceStrategyRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Polly.Telemetry;

Expand Down Expand Up @@ -36,6 +37,8 @@ public ResilienceStrategyRegistry()
/// Initializes a new instance of the <see cref="ResilienceStrategyRegistry{TKey}"/> class with a custom builder factory and comparer.
/// </summary>
/// <param name="options">The registry options.</param>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> are <see langword="null"/>.</exception>
public ResilienceStrategyRegistry(ResilienceStrategyRegistryOptions<TKey> options)
{
Guard.NotNull(options);
Expand All @@ -55,6 +58,7 @@ public ResilienceStrategyRegistry(ResilienceStrategyRegistryOptions<TKey> option
/// <param name="key">The key used to identify the resilience strategy.</param>
/// <param name="strategy">The resilience strategy instance.</param>
/// <returns>true if the strategy was added successfully, false otherwise.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="strategy"/> is <see langword="null"/>.</exception>
public bool TryAdd(TKey key, ResilienceStrategy strategy)
{
Guard.NotNull(strategy);
Expand Down Expand Up @@ -113,6 +117,7 @@ public override bool TryGet(TKey key, [NotNullWhen(true)] out ResilienceStrategy
/// <remarks>
/// Use this method when you want to create the strategy on-demand when it's first accessed.
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="configure"/> is <see langword="null"/>.</exception>
public bool TryAddBuilder(TKey key, Action<TKey, ResilienceStrategyBuilder> configure)
{
Guard.NotNull(configure);
Expand Down
1 change: 1 addition & 0 deletions src/Polly.Core/ResilienceContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ internal void InitializeFrom(ResilienceContext context)
/// Returns a <paramref name="context"/> back to the pool.
/// </summary>
/// <param name="context">The context instance.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="context"/> is <see langword="null"/>.</exception>
public static void Return(ResilienceContext context)
{
Guard.NotNull(context);
Expand Down
Loading

0 comments on commit f4d5347

Please sign in to comment.