Code Monkey home page Code Monkey logo

Comments (6)

blankor1 avatar blankor1 commented on June 26, 2024 1

@peter-csala Thank you for your detailed explanation!

So just to double confirm, only when we call the ExecuteAndCaptureAsync will we get the default TResult together with the exception in the DelegateResult. And if we just call ExecuteAsync, the exception will be thrown direct without creating a delegateResult. Is this correct?

Why there is delegation here not just the Result type? Is this delegation from the ExecuteAsync()?

Sorry, but I don't understand what do you mean here. Could you please rephrase it?

I see the point. Sry for the confusing. Please just ignore this.

from polly.

peter-csala avatar peter-csala commented on June 26, 2024 1

So just to double confirm, only when we call the ExecuteAndCaptureAsync will we get the default TResult together with the exception in the DelegateResult. And if we just call ExecuteAsync, the exception will be thrown direct without creating a DelegateResult. Is this correct?

I have to confess that I mixed DelegateResult and PolicyResult in my previous answer. 😥
Let me correct myself and answer your question as well.

DelegateResult

The DelegateResult captures the outcome of the decorated method's execution. And that information is passed to the sleepDurationProvider callback method as well as to the onRetry{Async} callback method. In other words, you can access the outcome of the current failed attempt inside the sleepDurationProvider and calculate the new sleep duration accordingly. You can also access this information inside the onRetry{Async} method.

Please bear in mind that not every overload receives a DelegateResult parameter!

So, this type is used to pass information about the execution of the decorated method to those custom callbacks that you can define during the policy declaration. Its usage is not limited to the Retry. Fallback (onFallback{Async}, fallbackAction) and Circuit Breaker (onBreak) also utilize it.

PolicyResult

The PolicyResult{<TResult>} captures the outcome of the policy's execution. This type has two variants: PolicyResult and PolicyResult<TResult>.

  • The former one is used when the policy is defined without TResult generic parameter. So, this class either captures information about the thrown Exception OR simply just the fact that the policy execution was successful.
  • The latter one is used when the policy is defined with TResult generic parameter. So, this class either captures information about the thrown Exception OR captures information about the result of the policy execution.

These classes are used only by the ExecuteAndCapture{Async} overloads. The Execute{Async} overloads do NOT wrap up the outcome of the policy execution. They either return with Task<TResult>|TResult or throw the exception.

Original question

/// The result of executing the delegate. Will be default(TResult) if an exception was thrown.

The second statement is not Polly specific. It is how C# and its type system works.

Let's me demonstrate it with the following fiddle: https://dotnetfiddle.net/GbjCFC

var dr1 = new DelegateResult<int>(1);
var dr2 = new DelegateResult<string>("a");

var dr3 = new DelegateResult<int>(new Exception());
var dr4 = new DelegateResult<string>(new Exception());

dr1.Dump();
dr2.Dump();
dr3.Dump();
dr4.Dump();

In case of dr3 the Result will be 0 which is default(int).
In case of dr4 the Result will be null which is default(string).

Sorry for the confusion. I hope this explains everything. If you have further questions then please let me know.

from polly.

peter-csala avatar peter-csala commented on June 26, 2024 1

I see. But for the sample code I provide in the question, if the SendRequest() method throw an exception, then it will not even create a DelegateResult and just terminate the Policy and throw the exception. Only when we are using Handle() and with some specific overload method will the DelegateResult be created and used. Is this correct?

Yes, that's correct. If the policy is not defined in a way to handle the thrown exception (either via the Handle or the Or builder methods) then it won't create a DelegateResult. As we discussed above, the DelegateResult is used by the sleepDurationProvider and by the onRetry{Async}. Since the exception is not handled from the policy perspective none of these custom defined delegates will be called.

Let me copy here the relevant code fragment:

catch (Exception ex)
{
    Exception handledException = shouldRetryExceptionPredicates.FirstMatchOrDefault(ex);
    if (handledException == null)
    {
        throw;
    }

    canRetry = tryCount < permittedRetryCount && (sleepDurationsEnumerator == null || sleepDurationsEnumerator.MoveNext());

    if (!canRetry)
    {
        handledException.RethrowWithOriginalStackTraceIfDiffersFrom(ex);
        throw;
    }

    outcome = new DelegateResult<TResult>(handledException);
}

The first throw; is called if the thrown exception is not a handled exception from the policy perspective

retry_flow_first_case

The second throw; is called if the thrown exception is handled but it run out of the allowed retry attempts.

retry_flow_second_case

from polly.

blankor1 avatar blankor1 commented on June 26, 2024 1

I see, Thank you so much for the detailed explanation!

from polly.

peter-csala avatar peter-csala commented on June 26, 2024

But if the exception is thrown, it should just terminate the retry and bubble up if we haven't set the Handle.
Through my testing, the exception also terminate the retry.

That's exactly how it should work. If an exception is thrown by the decorated method and the policy is not defined in a way to handle that then it will propagate the exception to the Execute{Async} caller.

On the related wiki page there is a dedicated flow diagram about this

retry flow diagram

What does this default(TResult) value in the XML comment means and what is its actual behavior.

If you call the ExecuteAndCapture{Async} then you will receive an DelegateResult<TResult> object.

If an exception was thrown then the Exception property is populated with the thrown exception.

outcome = new DelegateResult<TResult>(handledException);

If a result is returned then the Result object is populated.

outcome = new DelegateResult<TResult>(result);

Why there is delegation here not just the Result type? Is this delegation from the ExecuteAsync()?

Sorry, but I don't understand what do you mean here. Could you please rephrase it?

If so, will this DelegateResult.Result block the async call?

No, it does not. That .Result is NOT called on a Task<TResult> rather than on the DelegateResult. The DelegateResult is populated after the decorated method is already awaited. I can understand the confusion with the unfortunate name choice.

from polly.

blankor1 avatar blankor1 commented on June 26, 2024

I see. But for the sample code I provide in the question, if the SendRequest() method throw an exception, then it will not even create a DelegateResult and just terminate the Policy and throw the exception. Only when we are using Handle() and with some specific overload method will the DelegateResult be created and used. Is this correct?

from polly.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.