Skip to content

Instantly share code, notes, and snippets.

@Zodt
Last active January 10, 2022 15:06
Show Gist options
  • Save Zodt/3b9d8ac21d870c6f5adabd6dbe437fba to your computer and use it in GitHub Desktop.
Save Zodt/3b9d8ac21d870c6f5adabd6dbe437fba to your computer and use it in GitHub Desktop.
using System;
using System.Threading.Tasks;
namespace RetryPolicy
{
/// <summary>
/// A class that can execute a specific code block multiple times, using linear retries.
/// </summary>
internal class LinearRetryPolicy<TResult>
{
private readonly Func<Task<TResult>> _action;
private readonly Func<TResult, Task<bool>> _shouldRetry;
private readonly TimeSpan _delay;
private readonly int _maximumNumberOfAttempts;
/// <summary>
/// Creates an instance of the <see cref="LinearRetryPolicy{TResult}"/> class.
/// </summary>
/// <param name="action">Action to perform.</param>
/// <param name="shouldRetry">Should the action be retried based on the result?</param>
/// <param name="delay">Delay between runs.</param>
/// <param name="maximumNumberOfAttempts">Maximum number of attempts.</param>
public LinearRetryPolicy(
Func<Task<TResult>> action,
Func<TResult, Task<bool>> shouldRetry,
TimeSpan delay,
int maximumNumberOfAttempts)
{
_action = action;
_shouldRetry = shouldRetry;
_delay = delay;
_maximumNumberOfAttempts = maximumNumberOfAttempts;
}
/// <summary>
/// Executes the <see cref="LinearRetryPolicy{TResult}"/>.
/// </summary>
/// <returns>A <see cref="TResult"/> if a result could be retrieved, the default value for <see cref="TResult"/> otherwise.</returns>
public async Task<TResult> Execute()
{
for (var i = 0; i < _maximumNumberOfAttempts; i++)
{
var result = await _action();
if (!await _shouldRetry(result))
{
return result;
}
await Task.Delay(_delay);
}
throw new Exception("The number of runs exceeded the maximum number of attempts.");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment