From d6a2e91df9a334c479fcdf158ae1b238079ea29f Mon Sep 17 00:00:00 2001 From: Dixin Date: Wed, 24 Jan 2024 23:35:57 -0800 Subject: [PATCH] Add CancellationToken support to retry async methods. Fix typos in documents. --- .../Retry.Execute.cs | 16 +++++++---- .../Retry.ExponentialBackoff.cs | 28 +++++++++++-------- .../Retry.FixedInterval.cs | 18 ++++++++---- .../Retry.Incremental.cs | 18 ++++++++---- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/Source/TransientFaultHandling.Core/Retry.Execute.cs b/Source/TransientFaultHandling.Core/Retry.Execute.cs index 5257a09..701d71a 100644 --- a/Source/TransientFaultHandling.Core/Retry.Execute.cs +++ b/Source/TransientFaultHandling.Core/Retry.Execute.cs @@ -8,7 +8,7 @@ public static partial class Retry /// /// Repetitively executes the specified action while it satisfies the specified retry strategy. /// - /// he type of result expected from the executable action. + /// The type of result expected from the executable action. /// A delegate that represents the executable action that returns the result of type . /// The retry strategy. /// The predicate function to detect whether the specified exception is transient. @@ -48,22 +48,24 @@ public static partial class Retry /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. /// - /// he type of result expected from the executable asynchronous function. + /// The type of result expected from the executable asynchronous function. /// A asynchronous function that returns a started task (also known as "hot" task). /// The retry strategy. /// The predicate function to detect whether the specified exception is transient. /// The callback function that will be invoked whenever a retry condition is encountered. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task ExecuteAsync( Func> func, RetryStrategy? retryStrategy = null, Func? isTransient = null, - EventHandler? retryingHandler = null) + EventHandler? retryingHandler = null, + CancellationToken cancellationToken = default) { func.NotNull(); - return CreateRetryPolicy(retryStrategy, isTransient, retryingHandler).ExecuteAsync(func); + return CreateRetryPolicy(retryStrategy, isTransient, retryingHandler).ExecuteAsync(func, cancellationToken); } /// @@ -73,16 +75,18 @@ public static partial class Retry /// The retry strategy. /// The predicate function to detect whether the specified exception is transient. /// The callback function that will be invoked whenever a retry condition is encountered. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task ExecuteAsync( Func func, RetryStrategy? retryStrategy = null, Func? isTransient = null, - EventHandler? retryingHandler = null) + EventHandler? retryingHandler = null, + CancellationToken cancellationToken = default) { func.NotNull(); - return CreateRetryPolicy(retryStrategy, isTransient, retryingHandler).ExecuteAsync(func); + return CreateRetryPolicy(retryStrategy, isTransient, retryingHandler).ExecuteAsync(func, cancellationToken); } } \ No newline at end of file diff --git a/Source/TransientFaultHandling.Core/Retry.ExponentialBackoff.cs b/Source/TransientFaultHandling.Core/Retry.ExponentialBackoff.cs index cffe6f9..f9af122 100644 --- a/Source/TransientFaultHandling.Core/Retry.ExponentialBackoff.cs +++ b/Source/TransientFaultHandling.Core/Retry.ExponentialBackoff.cs @@ -5,7 +5,7 @@ public static partial class Retry /// /// Repetitively executes the specified action while it satisfies the specified retry strategy. /// - /// he type of result expected from the executable action. + /// The type of result expected from the executable action. /// A delegate that represents the executable action that returns the result of type . /// The number of retry attempts. /// The predicate function to detect whether the specified exception is transient. @@ -61,7 +61,7 @@ public static partial class Retry /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. /// - /// he type of result expected from the executable asynchronous function. + /// The type of result expected from the executable asynchronous function. /// A asynchronous function that returns a started task (also known as "hot" task). /// The number of retry attempts. /// The predicate function to detect whether the specified exception is transient. @@ -70,6 +70,7 @@ public static partial class Retry /// The maximum backoff time. /// The value that will be used to calculate a random delta in the exponential delay between retries. /// true to immediately retry in the first attempt; otherwise, false. The subsequent retries will remain subject to the configured retry interval. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task ExponentialBackoffAsync( @@ -80,12 +81,14 @@ public static partial class Retry TimeSpan? minBackoff = null, TimeSpan? maxBackoff = null, TimeSpan? deltaBackoff = null, - bool? firstFastRetry = null) => + bool? firstFastRetry = null, + CancellationToken cancellationToken = default) => ExecuteAsync( func.NotNull(), WithExponentialBackoff(retryCount, minBackoff, maxBackoff, deltaBackoff, firstFastRetry), isTransient, - retryingHandler); + retryingHandler, + cancellationToken); /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. @@ -98,6 +101,7 @@ public static partial class Retry /// The maximum backoff time. /// The value that will be used to calculate a random delta in the exponential delay between retries. /// true to immediately retry in the first attempt; otherwise, false. The subsequent retries will remain subject to the configured retry interval. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task ExponentialBackoffAsync( @@ -108,12 +112,14 @@ public static partial class Retry TimeSpan? minBackoff = null, TimeSpan? maxBackoff = null, TimeSpan? deltaBackoff = null, - bool? firstFastRetry = null) => + bool? firstFastRetry = null, + CancellationToken cancellationToken = default) => ExecuteAsync( func.NotNull(), WithExponentialBackoff(retryCount, minBackoff, maxBackoff, deltaBackoff, firstFastRetry), isTransient, - retryingHandler); + retryingHandler, + cancellationToken); /// /// Create a new instance of the class. @@ -126,11 +132,11 @@ public static partial class Retry /// The name of the retry strategy. /// A new instance of the class. public static ExponentialBackoff WithExponentialBackoff( - int? retryCount = null, - TimeSpan? minBackoff = null, - TimeSpan? maxBackoff = null, - TimeSpan? deltaBackoff = null, - bool? firstFastRetry = null, + int? retryCount = null, + TimeSpan? minBackoff = null, + TimeSpan? maxBackoff = null, + TimeSpan? deltaBackoff = null, + bool? firstFastRetry = null, string? name = null) => new( name, retryCount ?? RetryStrategy.DefaultClientRetryCount, diff --git a/Source/TransientFaultHandling.Core/Retry.FixedInterval.cs b/Source/TransientFaultHandling.Core/Retry.FixedInterval.cs index 442f5da..48bcf07 100644 --- a/Source/TransientFaultHandling.Core/Retry.FixedInterval.cs +++ b/Source/TransientFaultHandling.Core/Retry.FixedInterval.cs @@ -5,7 +5,7 @@ public static partial class Retry /// /// Repetitively executes the specified action while it satisfies the specified retry strategy. /// - /// he type of result expected from the executable action. + /// The type of result expected from the executable action. /// A delegate that represents the executable action that returns the result of type . /// The number of retry attempts. /// The predicate function to detect whether the specified exception is transient. @@ -53,13 +53,14 @@ public static partial class Retry /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. /// - /// he type of result expected from the executable asynchronous function. + /// The type of result expected from the executable asynchronous function. /// A asynchronous function that returns a started task (also known as "hot" task). /// The number of retry attempts. /// The predicate function to detect whether the specified exception is transient. /// The callback function that will be invoked whenever a retry condition is encountered. /// The time interval between retries. /// true to immediately retry in the first attempt; otherwise, false. The subsequent retries will remain subject to the configured retry interval. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task FixedIntervalAsync( @@ -68,12 +69,14 @@ public static partial class Retry Func? isTransient = null, EventHandler? retryingHandler = null, TimeSpan? retryInterval = null, - bool? firstFastRetry = null) => + bool? firstFastRetry = null, + CancellationToken cancellationToken = default) => ExecuteAsync( func.NotNull(), WithFixedInterval(retryCount, retryInterval, firstFastRetry), isTransient, - retryingHandler); + retryingHandler, + cancellationToken); /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. @@ -84,6 +87,7 @@ public static partial class Retry /// The callback function that will be invoked whenever a retry condition is encountered. /// The time interval between retries. /// true to immediately retry in the first attempt; otherwise, false. The subsequent retries will remain subject to the configured retry interval. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task FixedIntervalAsync( @@ -92,12 +96,14 @@ public static partial class Retry Func? isTransient = null, EventHandler? retryingHandler = null, TimeSpan? retryInterval = null, - bool? firstFastRetry = null) => + bool? firstFastRetry = null, + CancellationToken cancellationToken = default) => ExecuteAsync( func.NotNull(), WithFixedInterval(retryCount, retryInterval, firstFastRetry), isTransient, - retryingHandler); + retryingHandler, + cancellationToken); /// /// Create a new instance of the class. diff --git a/Source/TransientFaultHandling.Core/Retry.Incremental.cs b/Source/TransientFaultHandling.Core/Retry.Incremental.cs index 3dbf5bb..1d3e24a 100644 --- a/Source/TransientFaultHandling.Core/Retry.Incremental.cs +++ b/Source/TransientFaultHandling.Core/Retry.Incremental.cs @@ -5,7 +5,7 @@ public static partial class Retry /// /// Repetitively executes the specified action while it satisfies the specified retry strategy. /// - /// he type of result expected from the executable action. + /// The type of result expected from the executable action. /// A delegate that represents the executable action that returns the result of type . /// The number of retry attempts. /// The predicate function to detect whether the specified exception is transient. @@ -57,7 +57,7 @@ public static partial class Retry /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. /// - /// he type of result expected from the executable asynchronous function. + /// The type of result expected from the executable asynchronous function. /// A asynchronous function that returns a started task (also known as "hot" task). /// The number of retry attempts. /// The predicate function to detect whether the specified exception is transient. @@ -65,6 +65,7 @@ public static partial class Retry /// The initial interval that will apply for the first retry. /// The incremental time value that will be used to calculate the progressive delay between retries. /// true to immediately retry in the first attempt; otherwise, false. The subsequent retries will remain subject to the configured retry interval. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task IncrementalAsync( @@ -74,12 +75,14 @@ public static partial class Retry EventHandler? retryingHandler = null, TimeSpan? initialInterval = null, TimeSpan? increment = null, - bool? firstFastRetry = null) => + bool? firstFastRetry = null, + CancellationToken cancellationToken = default) => ExecuteAsync( func.NotNull(), WithIncremental(retryCount, initialInterval, increment, firstFastRetry), isTransient, - retryingHandler); + retryingHandler, + cancellationToken); /// /// Repeatedly executes the specified asynchronous function while it satisfies the current retry policy. @@ -91,6 +94,7 @@ public static partial class Retry /// The initial interval that will apply for the first retry. /// The incremental time value that will be used to calculate the progressive delay between retries. /// true to immediately retry in the first attempt; otherwise, false. The subsequent retries will remain subject to the configured retry interval. + /// The token used to cancel the retry operation. This token does not cancel the execution of the asynchronous task. /// Returns a task that will run to completion if the original task completes successfully (either the first time or after retrying transient failures). If the task fails with a non-transient error or the retry limit is reached, the returned task will transition to a faulted state and the exception must be observed. /// func public static Task IncrementalAsync( @@ -100,12 +104,14 @@ public static partial class Retry EventHandler? retryingHandler = null, TimeSpan? initialInterval = null, TimeSpan? increment = null, - bool? firstFastRetry = null) => + bool? firstFastRetry = null, + CancellationToken cancellationToken = default) => ExecuteAsync( func.NotNull(), WithIncremental(retryCount, initialInterval, increment, firstFastRetry), isTransient, - retryingHandler); + retryingHandler, + cancellationToken); /// /// Create a new instance of the class.