I creating a list of Tasks and executing them with Task.WhenAll(). If an http request returns error status I want to retry the call.
I'm getting and error on this line: ExecuteAsync(() => func()));
Cannot implicitly convert type 'System.Threading.Tasks.Task' to'System.Threading.Tasks.Task<System.Net.HttpWebResponse>'
I know what the error means, but the part I need help with is the overall implementation of Polly with parallel http calls and checking the response status.
Code:
var tasks = new List<Task<string>>();
var policy = Policy
.Handle<HttpRequestException>()
.OrResult<HttpWebResponse>(a => a.StatusCode != HttpStatusCode.OK)
.WaitAndRetryForeverAsync(i => pauseBetweenFailures);
var urls = new List<string>();
foreach (var mediaItem in UploadedMediaItems)
{
var mediaRequest = new HttpRequestMessage
{
RequestUri = new Uri("****"),
Method = HttpMethod.Get,
Headers = {
{ "id-token", id_Token },
{ "access-token", access_Token }
}
};
async Task<string> func()
{
var response = await client.SendAsync(mediaRequest);
return await response.Content.ReadAsStringAsync();
}
tasks.Add(policy.ExecuteAsync(() => func()));
}
await Task.WhenAll(tasks);
foreach (var t in tasks)
{
var postResponse = await t;
urls.Add(postResponse);
}
Disregarding any other issues (conceptual or otherwise)
You have the wrong generic parameter HttpWebResponse
, it should be HttpResponseMessage
as that is what SendAsync
returns
var policy = Policy
.Handle<HttpRequestException>()
.OrResult<HttpResponseMessage>(a => a.StatusCode != HttpStatusCode.OK)
...
Also, seemingly you would want to apply the policy to the SendAsync
method, not the local method that returns a Task<string>
async Task<string> func()
{
var response = await policy.ExecuteAsync(() => client.SendAsync(mediaRequest));
return await response.Content.ReadAsStringAsync();
}
tasks.Add(func());
Also note, that you will need to recreate a new HttpRequestMessage
for every retry. They cannot be reused.
Which may look more like this
Task<HttpResponseMessage> Send()
{
var mediaRequest = new HttpRequestMessage {... };
return client.SendAsync(mediaRequest);
}
async Task<string> func()
{
var response = await policy.ExecuteAsync(Send);
return await response.Content.ReadAsStringAsync();
}
tasks.Add(func());
However, on saying all this, you would likely want to use the more modern approach of adding Polly to the IHttpClientFactory
implementation when you register the service via AddPolicyHandler
, which will in turn take care of the request