Skip to content

Instantly share code, notes, and snippets.

@sleemer
Last active October 10, 2016 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sleemer/5a2e0f549dd11f625054770ec043c218 to your computer and use it in GitHub Desktop.
Save sleemer/5a2e0f549dd11f625054770ec043c218 to your computer and use it in GitHub Desktop.
Rx extension method to retry with delay strategy
using System;
using System.Reactive.Linq;
namespace Common
{
public static class ReactiveExtensions
{
private static Func<int, TimeSpan> DefaultDelayStrategy = n => n == 1 ? TimeSpan.Zero : TimeSpan.FromSeconds(Math.Pow(2, n - 1));
/// <summary>
/// Repeats the <paramref name="source"> observable sequence the specified number of times or untill it successfully terminates.
/// It will wait before trying again for a certain amount of time (in seconds).
/// Waiting period depends on number of attempts and Strategy.
/// </summary>
/// <param name="source">Observable sequence to repeat</param>
/// <param name="retryCount">Number of times to repeat the sequence</param>
/// <param name="retryOnError">A function to test each occured exception for a condition</param>
/// <param name="delayStrategy">
/// A function to calculate amount of time to wait before next attempt.
/// If it's null then Default Strategy Math.Pow(2, n - 1) will be used, where n is a number of attempt.
/// </param>
public static IObservable<T> RetryWithBackoffStrategy<T>(
this IObservable<T> source,
int retryCount,
Predicate<Exception> retryOnError = null,
Func<int, TimeSpan> delayStrategy = null)
{
retryOnError = retryOnError ?? (_ => true);
delayStrategy = delayStrategy ?? DefaultDelayStrategy;
IObservable<T> repeatableObservable = null;
int attempt = 0;
repeatableObservable = Observable.Defer(
() => source
.DelaySubscription(delayStrategy(++attempt))
.Catch<T, Exception>(
ex => (attempt == retryCount || !retryOnError(ex))
? Observable.Throw<T>(ex)
: repeatableObservable
)
);
return repeatableObservable
.Repeat();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment