Reputation: 31
So I have 2 queries:
var a = await _aQuery.Execute(aId);
var b = await _bQuery.Execute(bId);
How can I retry execution of these queries with Polly Retry so that if any of them succeeds to get a non-null value, the code can proceed?
For example: 5 retries every 200ms and if query succeeds on a
or on b
, break the retries and proceed.
Upvotes: 1
Views: 891
Reputation: 22819
Let me alter your two operations a bit for the sake of simplicity.
static Random rnd = new();
static async Task<int?> OperationA()
{
await Task.Delay(100); //Simulate I/O call's latency
var number = rnd.Next();
return number % 5 == 0 ? number : null;
}
static async Task<int?> OperationB()
{
await Task.Delay(100); //Simulate I/O call's latency
var number = rnd.Next();
return number % 4 == 0 ? number + 1 : null;
}
OperationA
and OperationB
) and they will either return null
or an int
Now If you need to define a retry policy which
then you can do that like this:
var retryUntilGetResult = Policy<(int?, int?)>
.HandleResult(((int? OpA, int? OpB) results) => !results.OpA.HasValue && !results.OpB.HasValue)
.WaitAndRetryAsync(retryCount: 5, _ => TimeSpan.FromMilliseconds(200));
Policy<(int?, int?)>
part says that your return type is a tuple with two nullable integersHandleResult
part says that if the returned tuple (results
) does not contain any integer (!...HasValue
) then the policy should triggerWaitAndRetryAsync
part says you want to decorate an async method with this policyThe usage of this policy looks like this:
var result = await retryUntilGetResult.ExecuteAsync(async () =>
{
Task<int?> opA = OperationA();
Task<int?> opB = OperationB();
await Task.WhenAll(opA, opB);
return (await opA, await opB);
});
For the sake of completeness here the full source code:
static async Task Main()
{
var retryUntilGetResult = Policy<(int?, int?)>
.HandleResult(((int? OpA, int? OpB) results) => !results.OpA.HasValue && !results.OpB.HasValue)
.WaitAndRetryAsync(retryCount: 5, _ => TimeSpan.FromMilliseconds(200));
var result = await retryUntilGetResult.ExecuteAsync(async () =>
{
Task<int?> opA = OperationA();
Task<int?> opB = OperationB();
await Task.WhenAll(opA, opB);
return (await opA, await opB);
});
Console.WriteLine(result);
}
static Random rnd = new();
static async Task<int?> OperationA()
{
await Task.Delay(100); //Simulate I/O call's latency
var number = rnd.Next();
return number % 5 == 0 ? number : null;
}
static async Task<int?> OperationB()
{
await Task.Delay(100); //Simulate I/O call's latency
var number = rnd.Next();
return number % 4 == 0 ? number + 1 : null;
}
Upvotes: 3