Polly icon indicating copy to clipboard operation
Polly copied to clipboard

Conditional retry

Open fenomeno83 opened this issue 3 years ago • 6 comments

Hi.

My actual polly retry configuration

services.AddHttpClient("RetryClient")
        .AddPolicyHandler((services, request) => HttpPolicyExtensions.HandleTransientHttpError()
        .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
        onRetry: (outcome, timespan, retryAttempt, context) =>
        {

           //log
        }
        ));

When I retry I need to make some check on db -if check is ok, retry -if is not ok, return response error (like retry is not enabled)

How can make configuration?

thanks

fenomeno83 avatar Apr 10 '21 10:04 fenomeno83

Hi there - I don't fully understand your question.

It seems you're trying to use a retry in the opposite way to how it's usually intended, where retries occur when there's a exception - not when it's successful. Your code example is also related to HTTP calls, but you talk of checking a database?

martincostello avatar Apr 11 '21 16:04 martincostello

Hi. I try to explain better.

This is pseudocode where I made a Httpclient post request

 var exists= CheckIfExistsInDatabase(request);

if(exists){
   return "exists";
}
else{
  //make request 
   var httpClient = _clientFactory.CreateClient("RetryClient"); //httpclient with polly retry

  var responseBody = await httpClient.PostAsync("service/create", request, Encoding.UTF8, "application/json"));
  if(responseBody.IsSuccessStatusCode)
     return "created";
 else
    return "error";
      

 }

In this example, before do httpclient I need to do some check on db (CheckIfExistsInDatabase) to understand if I can do request or not.

But, if I have some connection issue, I need to re-check on db before retry request, because in the meanwhile that check could became"true" and in this case I can't do request.

So, on polly retry I need to call "CheckIfExistsInDatabase". If result is false, proceed as usual(retry to do request), otherwise I can't do request but need to return "exists".

fenomeno83 avatar Apr 11 '21 16:04 fenomeno83

In that case, it would be better to wrap the retry policy around the whole method where you do the existence check and the HTTP call and not have the retry configured at the HTTP layer. Otherwise it's transparent to your code and won't have access to your business logic for checking the database.

martincostello avatar Apr 11 '21 16:04 martincostello

Hi, how can I wrap Check+Http to retry using polly? Can you make an example? thanks

fenomeno83 avatar Apr 11 '21 16:04 fenomeno83

Something like this:

public async Task<string> YourMethodThatDoesThings(SomeType request)
{
    return await Polly.Handle<WhateverException>()
               .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)))
               .ExecuteAsync(() =>
               {
                   var exists = = CheckIfExistsInDatabase(request);

                   if (exists) {
                       return "exists";
                   }

                   var httpClient = _clientFactory.CreateClient();

                   var responseBody = await httpClient.PostAsync("service/create", request, Encoding.UTF8, "application/json"));

                   return responseBody.IsSuccessStatusCode ? "created" : "error";
               });
}

martincostello avatar Apr 11 '21 17:04 martincostello

thanks!

fenomeno83 avatar Apr 11 '21 19:04 fenomeno83

@fenomeno83

The predicates in v8 are much more powerful and allow you to access the context or make external asynchronous calls.

See this example: https://github.com/App-vNext/Polly/blob/v8-fixed-issues/src/Polly.Core.Tests/Issues/IssuesTests.FlowingContext_849.cs

This issue will be closed once v8 is released.

martintmk avatar Apr 25 '23 09:04 martintmk

The alpha is released, and you can try this out.

https://www.nuget.org/packages/Polly

Closing the issue.

martintmk avatar Jun 26 '23 11:06 martintmk