Polly
Polly copied to clipboard
[Question]: Is it recommended to use ResiliencePipeline instance as a singleton?
What are you wanting to achieve?
Hello,
Great job! A quick question, when I'm not using the .net core DI and I was wondering if I can use safely a single instance of ResiliencePipeline to make async calls with retries?
Thanks
What code or approach do you have so far?
I don't think this needs code. :)
Additional context
No response
Yes you can 🙂
Please bear in mind that it is safe only if you create a new ResilienceContext per execution!
New context for each execution
var taskIdKey = new ResiliencePropertyKey<int>("TaskId");
var pipeline = new ResiliencePipelineBuilder<string>()
.AddRetry(new RetryStrategyOptions<string>()
{
MaxRetryAttempts = 10,
Delay = TimeSpan.FromSeconds(1),
ShouldHandle = new PredicateBuilder<string>().HandleResult(string.IsNullOrWhiteSpace),
OnRetry = args =>
{
var taskId = args.Context.Properties.GetValue<int>(taskIdKey, -1);
Console.WriteLine($"Task Id #{taskId} has its {args.AttemptNumber}th retry attempt");
return default;
}
})
.Build();
List<Task> tasks = [];
List<ResilienceContext> contexts = [];
for(int i = 0; i < 10; i++)
{
var context = ResilienceContextPool.Shared.Get(); // new context
tasks.Add(pipeline.ExecuteAsync(async (ctx, taskId) =>
{
ctx.Properties.Set(taskIdKey, taskId);
await Task.Delay(500);
return string.Empty;
}, context, i).AsTask());
contexts.Add(context);
}
await Task.WhenAll(tasks);
contexts.ForEach(ctx => ResilienceContextPool.Shared.Return(ctx));
The ouput will be something like this:
Task Id #0 has its 0th retry attempt
Task Id #1 has its 0th retry attempt
Task Id #2 has its 0th retry attempt
Task Id #3 has its 0th retry attempt
Task Id #4 has its 0th retry attempt
Task Id #6 has its 0th retry attempt
Task Id #7 has its 0th retry attempt
Task Id #8 has its 0th retry attempt
Task Id #5 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #0 has its 1th retry attempt
Task Id #2 has its 1th retry attempt
Task Id #1 has its 1th retry attempt
Task Id #3 has its 1th retry attempt
Task Id #5 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #9 has its 1th retry attempt
Task Id #8 has its 1th retry attempt
Task Id #7 has its 1th retry attempt
Task Id #4 has its 1th retry attempt
Task Id #0 has its 2th retry attempt
Task Id #1 has its 2th retry attempt
Task Id #2 has its 2th retry attempt
Task Id #3 has its 2th retry attempt
Task Id #5 has its 2th retry attempt
Task Id #8 has its 2th retry attempt
Task Id #7 has its 2th retry attempt
Task Id #9 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #4 has its 2th retry attempt
Task Id #3 has its 3th retry attempt
Task Id #0 has its 3th retry attempt
Task Id #2 has its 3th retry attempt
Task Id #1 has its 3th retry attempt
Task Id #7 has its 3th retry attempt
Task Id #5 has its 3th retry attempt
Task Id #9 has its 3th retry attempt
Task Id #4 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #8 has its 3th retry attempt
Task Id #3 has its 4th retry attempt
...
The same context for all execution
var taskIdKey = new ResiliencePropertyKey<int>("TaskId");
var pipeline = new ResiliencePipelineBuilder<string>()
.AddRetry(new RetryStrategyOptions<string>()
{
MaxRetryAttempts = 10,
Delay = TimeSpan.FromSeconds(1),
ShouldHandle = new PredicateBuilder<string>().HandleResult(string.IsNullOrWhiteSpace),
OnRetry = args =>
{
var taskId = args.Context.Properties.GetValue<int>(taskIdKey, -1);
Console.WriteLine($"Task Id #{taskId} has its {args.AttemptNumber}th retry attempt");
return default;
}
})
.Build();
List<Task> tasks = [];
var context = ResilienceContextPool.Shared.Get(); //shared context
for(int i = 0; i < 10; i++)
{
tasks.Add(pipeline.ExecuteAsync(async (ctx, taskId) =>
{
ctx.Properties.Set(taskIdKey, taskId);
await Task.Delay(500);
return string.Empty;
}, context, i).AsTask());
}
await Task.WhenAll(tasks);
ResilienceContextPool.Shared.Return(context);
The ouput will be something like this:
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #9 has its 0th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 1th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 2th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 3th retry attempt
Task Id #6 has its 4th retry attempt
...