How can i improve this code so that the retry applies to all the exceptions which needs retry by default
public static readonly AsyncPolicy RetryPolicy = Policy
.Handle<Exception>()
.RetryAsync(3);
The SendAsync
operation can throw the following exceptions:
ArgumentNullException
when the request was null
InvalidOperationException
when the request message was already sent by the HttpClient instance
HttpRequestException
when the request failed due to an underlying issue such as network connectivity, DNS failure, server certificate validation or timeout
TaskCanceledException
when the request failed due to timeout (.NET Core and .NET 5 and later only)
OperationCanceledException
when the cancellation token was canceled (This exception is stored into the returned task)
Retrying on the first two exceptions will not change anything on the outcome. It will still fail with the exact same exception. These exceptions are indicating problem on the caller side.
The TaskCanceledException
is derived from the OperationCanceledException
. So, if you want to retry in both cases then it is enough to handle only the latter one.
public static readonly AsyncPolicy RetryPolicy = Policy
.Handle<HttpRequestException>()
.Or<OperationCanceledException>()
.RetryAsync(3);
The above section covered only those cases when the SendAsync
failed with an exception. But there might be cases where the SendAsync
did not fail but the sent request were not processed. The SendAsync
returns an HttpResponseMessage
object and its StatusCode
property could indicate retryable problems. Typical retryable status codes:
The internal server error usually treated as retryable status code but it really depends on the downstream system's implementation. You might have called an endpoint which has a bug. Re-issuing the same request most probably will not result in a different status code than 500.
If you look at the remarks of the AddTransientHttpErrorPolicy
then you can see that it will register a retry policy which triggers for one of the following conditions:
HttpRequestException
)This could be a good starting point but you might extend the triggers with one of the above mentioned exceptions and/or status codes.
Please bear in mind that not all operations are retryable. Requests which are creating new resources (usually POST requests in REST) might result in unwanted duplicates. If the downstream system is not prepared for de-duplication then you should try to avoid retries.
Here I have detailed the considerations for retry.