-1

I have the following code:

var expirationPeriodMilliseconds = 1000;
return Policy
   .HandleResult<EnquiryResult>(message => message.Status == EnquiryStatus.SystemError)
   .RetryForeverAsync() // instead run until expirationPeriodMilliseconds
   .ExecuteAsync(async () => await ratingProvider.Enquire(request, cancellationToken));

Is there any solution for polly to use the retry option for a certain period of time?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Andrei
  • 119
  • 1
  • 1
  • 10
  • Did you check the *other* `.RetryXXX` or `WaitAndRetry` methods ? Retry immediatelly or after a period? If the code retries immediatelly after a server fault the most likely outcome is to get the same fault. – Panagiotis Kanavos Aug 01 '18 at 14:01
  • 1
    Simply saying if EnquiryStatus.SystemError occurs I want to retry constantly for 1000 milliseconds. – Andrei Aug 01 '18 at 14:09
  • You can use multiple policies, eg a Retry and Timeout. This was asked in [this issue from 2016](https://github.com/App-vNext/Polly/issues/184). You can wrap the `RetryForeverAsync` inside a `Timeout` with `myTimeout.Wrap(myRetry)` – Panagiotis Kanavos Aug 01 '18 at 14:18
  • More also in this question: https://stackoverflow.com/a/43205503 – mountain traveller Aug 01 '18 at 16:24

1 Answers1

0

Even though it is a later answer it might be helpful for future readers

The policy definitions

var globalTimeoutPolicy = Policy
    .TimeoutAsync<EnquiryResult>(TimeSpan.FromMilliseconds(expirationPeriodMilliseconds));

var retryForeverPolicy = Policy
   .HandleResult<EnquiryResult>(message => message.Status == EnquiryStatus.SystemError)
   .RetryForeverAsync();

var combinedPolicy = Policy.WrapAsync(globalTimeoutPolicy, retryForeverPolicy);
  • Here we have defined two policies
    • One for retrying the same action over and over again if it receives SystemError
    • Another to terminate the action after N milliseconds
  • Finally we have chained/combined the policies into one
    • Because the globalTimeoutPolicy has been passed first to the WrapAsync that's why it is the outer policy so this timeout overarches all retry attempts
    • If we would pass the globalTimeoutPolicy as the second parameter of the WrapAsync then this timeout constraint would apply for each individual retry attempts

The usage of the chained policies

try
{
    var result = await combinedPolicy.ExecuteAsync(
         async (ct) => await ratingProvider.Enquire(request, ct), cancellationToken);
    Console.WriteLine($"Method has successfully completed with status: '{result.Status}'.");
}
catch(TimeoutRejectedException)
{
    Console.WriteLine($"Method has failed after retrying for {expirationPeriodMilliseconds}ms.");
}
  • Because your ratingProvider.Enquire method anticipates a CancellationToken that's why we can use Optimistic timeout strategy
    • Polly will link together your cancellationToken with the TimeoutPolicy's CancellationToken
  • If the timeout triggers and all previous retry attempts returned with SystemError then the ExecuteAsync will thrown an TimeoutRejectedException
Peter Csala
  • 17,736
  • 16
  • 35
  • 75