Last active
October 10, 2016 20:15
-
-
Save sleemer/5a2e0f549dd11f625054770ec043c218 to your computer and use it in GitHub Desktop.
Rx extension method to retry with delay strategy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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