-1

I have the following code to call the bank api, and convert the response into the object.

public static async Task<ExchangeModel> LoadExchange(string currency, string date)
{
    string url = "here is the bank's api url";

    var streamTask = await _clientPolicy.LinearHttpRetry.ExecuteAsync(
        () => _client.GetStreamAsync(url));
    var deserialized = await JsonSerializer.DeserializeAsync<Root>(await streamTask);
    var rate = deserialized.ExchangeModel.FirstOrDefault(r => r.Currency == currency);
    return rate;
}

I wanted to add polly in order to retry api call if it failed. To do so, I created a policy client, but I don't know how to check if GetStreamAsync is succeed as it is a System.IO.Stream and it has no succeed status or something.

public AsyncRetryPolicy<System.IO.Stream> LinearHttpRetry { get; }

public ClientPolicy()
{
    LinearHttpRetry = Policy.HandleResult<System.IO.Stream>(
        res => !res.IsSuccessStatusCode).
        WaitAndRetryAsync(5, retryAttempts => TimeSpan.FromSeconds(3));
}

In this example I kept it !res.IsSuccessStatusCode but there is no such parameter in my case.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Palamar66
  • 212
  • 1
  • 9
  • If you use HttpClientFactory this is handled the same way as any other HttpClient call. `it has no succeed status or smth.` on the contrary, failures raise an HTTP exception whose Status contains the HTTP status code, so Polly knows whether it's a server error, a 429 etc. The same applies to `GetStringAsync()`. In fact, in .NET 6 you could replace all the code with [GetFromJsonAsync()](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.json.httpclientjsonextensions.getfromjsonasync?view=net-6.0) and HttpClientFactory – Panagiotis Kanavos Sep 27 '22 at 12:11
  • 1
    The article [Use IHttpClientFactory to implement resilient HTTP requests](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests) shows how you can use HttpClientFactory to generate HttpClient instances already configured with the Polly policies you want. – Panagiotis Kanavos Sep 27 '22 at 12:16

1 Answers1

0

Rather than calling directly the GetStreamAsync you can do the following "trick":

var response = await _client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
//TODO: Check response status code then
using var stream = await response.Content.ReadAsStreamAsync();

First you need to alter your policy definition like this:

public IAsyncPolicy<HttpResponseMessage> LinearHttpRetry { get; }

public ClientPolicy()
{
    LinearHttpRetry = Policy
        .HandleResult<HttpResponseMessage>(res => !res.IsSuccessStatusCode)
        .WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(3));
}

Then you need to adjust the usage as well

public static async Task<ExchangeModel> LoadExchange(string currency, string date)
{
    string url = "here is the bank's api url";

    var response = await _clientPolicy.LinearHttpRetry.ExecuteAsync(
        async () => await _client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead));

    using var stream = await response.Content.ReadAsStreamAsync();
    var deserialized = await JsonSerializer.DeserializeAsync<Root>(stream);
    var rate = deserialized.ExchangeModel.FirstOrDefault(r => r.Currency == currency);
    return rate;
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75