App-vNext / Polly

Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. From version 6.0.1, Polly targets .NET Standard 1.1 and 2.0+.
https://www.thepollyproject.org
BSD 3-Clause "New" or "Revised" License
13.44k stars 1.23k forks source link

How to get error response before retry. #766

Closed ManjuN390 closed 4 years ago

ManjuN390 commented 4 years ago

Summary: What are you wanting to achieve?


Hi we have defined a policy, that i will be consuming form viewmodel, whenever error throw in server side, it will retry. Before retry i want to set one property in ViewModel so i need a callback of error response.

What code or approach do you have so far?

var retryPolicy =   Policy
        .Handle<ServiceException>()
        .WaitAndRetryForeverAsync(timespan, (exception, timespan) => {
                     // retry no issue i can log the error over here.
        });

But how to return error response to caller method to the viewmodel before retry ?

i will be calling the policy from Viewmodel as below,

bool isError = await retryPolicy.ExecuteAsync(=>(method) );

before retry i want to set the value isError = true;

please help on these.

reisenberger commented 4 years ago

@ManjuN390 . I may not have fully understood the question, so please clarify if that would help.

If policy declaration and consumption are in the same scope, you could just use a closure to modify the isError variable:

.WaitAndRetryForeverAsync(timespan, (exception, timespan) => {
                 isError = true;
    }

If policy declaration and consumption are not in the same scope (which is very common), you can pass information between different parts of the execution using Polly.Context.

For example, you could assign context["ViewModel"] = /* assign the ViewModel */, and then retrieve and modify the value, if needed, in the onRetry delegate or onRetryAsync delegate. This configuration overload takes an onRetry delegate which has access to Context; or this overload if you need an asynchronous onRetryAsync delegate.

There are more examples of this latter technique in the wiki page previously linked.

Does this help?

ManjuN390 commented 4 years ago

Thank you @reisenberger for kind response, i got the solution posting the same below.

Referred below URL to find sol. https://github.com/App-vNext/Polly/commit/1031967b11070674afe029d93ac4c465660e80ab

Defined policy as below to get callback event before retry,

    public static Policy RetryWithCallback(Action<Exception, TimeSpan> onRetryAsync)
    {
        return Policy
            .Handle<Exception>
            .WaitAndRetryForeverAsync(timespan, onRetryAsync);
    }

From ViewModel: trying to call server method, which will internally fetches data from server.

bool IsError = await serverMethodToFetchData(
                        t,
                        onRetry);

onRetry is the callback method written in Viemodel to perform some business logic, which will be here in above code to set the IsErrror property.

    private void onRetry(Exception exc, TimeSpan ts)
    {
     //buisness logic
    }

Below are server method implementation just for information.

    public static Task<bool> serverMethodToFetchData( 
        Action<Exception, TimeSpan> onRetryAsync = null)
    {
           //consuming the Policy defined for retry
           var urls = await Policy.RetryWithCallback(onRetryAsync).ExecuteAsync(t =>
            {
               // server call, if fails callback event(onRetryAsync) defined in Viewmodel onRetry will be notified.
            });
    }
reisenberger commented 4 years ago

Yes, if you declare the policy dynamically, you can also declare just the onRetryAsync in the scope where you wish to modify variables/properties in the same scope, and pass the onRetryAsync to the policy declaration.