debugcsharpMinorCanonical
General Retry Strategy #2
Viewed 0 times
strategyretrygeneral
Problem
Previous version
Now supports async operations and cancellation.
Let’s say we copy some file using retry strategy (it might be blocked, etc.). App code comes bellow:
Where:
Library code is a way longer now - anybody see a way to simplify?
And NULL Object pattern:
```
class Never : Try
{
public override voi
Now supports async operations and cancellation.
Let’s say we copy some file using retry strategy (it might be blocked, etc.). App code comes bellow:
class Processor
{
public void CopyData() =>
CopyData(IOTry.Slow);
public void CopyData(Try loop) =>
loop.Execute(() =>
File.Copy(@"c\a.txt", @"c:\b.txt"));
}Where:
public class IOTry
{
public static readonly Try Slow = Try.Retry(delay: 1000, times: 4, ratio: 3);
public static readonly Try Fast = Try.Retry(delay: 100, times: 4, ratio: 3);
}Library code is a way longer now - anybody see a way to simplify?
public abstract class Try
{
public static readonly Try Never = new Never();
public static readonly Try Once = Retry(delay: 0, times: 0, ratio: 0);
public static Try Retry(int delay, int times, double ratio) =>
RetryAfter(from i in Enumerable.Range(0, times)
select delay * Math.Pow(ratio, i) into d
select (int)d);
public static Try RetryAfter(params int[] delays) => RetryAfter(delays.AsEnumerable());
public static Try RetryAfter(IEnumerable delays) => new Retry(delays);
public void Execute(Action action) => Execute(action, CancellationToken.None);
public abstract void Execute(Action action, CancellationToken cancellationToken);
public Task ExecuteAsync(Action action) => ExecuteAsync(action, CancellationToken.None);
public Task ExecuteAsync(Action action, CancellationToken cancellationToken) =>
ExecuteAsync(() => { action(); return Task.CompletedTask; }, cancellationToken);
public Task ExecuteAsync(Func action) => ExecuteAsync(action, CancellationToken.None);
public abstract Task ExecuteAsync(Func action, CancellationToken cancellationToken);
public Try FailFast() => FailFast(0);
public Try FailFast(int timeout) => new Breaker(this, timeout);
}And NULL Object pattern:
```
class Never : Try
{
public override voi
Solution
I was just going to borrow your code and implement it in my application ;-) but there is one thing that I'm missing here. I needed to know which exceptions were thrown.
That's why I want to suggest you to extend the framework so that after the retries are finished you can log what happened.
I could imagine the new API like this:
where the second lambda passes either each exception that occured or a collection of exceptions or an
The API could either pass each exception that occured right away or collect them and pass them to me when the retry is finished. I'm not sure what could work best.
That's why I want to suggest you to extend the framework so that after the retries are finished you can log what happened.
I could imagine the new API like this:
class Processor
{
private readonly ILogger _logger = ...;
public void CopyData() =>
CopyData(IOTry.Slow);
public void CopyData(Try loop) =>
loop.Execute(() =>
File.Copy(@"c\a.txt", @"c:\b.txt"),
ex => _logger.Log(ex)
);
}where the second lambda passes either each exception that occured or a collection of exceptions or an
AggregateException - perhaps all three APIs make sense in different situations.The API could either pass each exception that occured right away or collect them and pass them to me when the retry is finished. I'm not sure what could work best.
Code Snippets
class Processor
{
private readonly ILogger _logger = ...;
public void CopyData() =>
CopyData(IOTry.Slow);
public void CopyData(Try loop) =>
loop.Execute(() =>
File.Copy(@"c\a.txt", @"c:\b.txt"),
ex => _logger.Log(ex)
);
}Context
StackExchange Code Review Q#140233, answer score: 2
Revisions (0)
No revisions yet.