With Polly I'd like to have my policy definition and the execution of that policy in two different statements, as in:
// Policy definition
var policy = Policy
.HandleResult<IRestResponse>(predicate)
.Retry(2);
// Policy execution
policy.ExecuteAndCapture(() =>
{
DoSomethingAndReturnAnIRestResponse();
};
I want to do it this way so I can get better reuse of my retry policies, e.g. for use in dependency injection.
I'm trying to understand if there's any considerations when splitting up the policy and the execution in this way, for example if there's any "state" (for lack of a better term) that might not carry in the policy
object from policy definition to execution.
Along these lines I'm noticing that when I use Polly's ExecuteAndCapture()
in the above fashion that certain properties (those related to capturing the final exception/outcome, associated with ExecuteAndCapture()
) aren't showing on the policy
object. Per the documentation (here and here), upon completion of a policy such as the below:
var policy = Policy
.HandleResult<IRestResponse>(predicate)
.Retry(2)
.ExecuteAndCapture(() =>
{
DoSomethingAndReturnAnIRestResponse();
});
...you are supposed to get back:
PolicyResult.Outcome
PolicyResult.FinalException
PolicyResult.ExceptionType
PolicyResult.Result
This indeed is happening then the ExecuteAndCapture()
is in the same statement as the policy definition. However, when separating the policy definition from the execution those properties aren't available. I naively assumed they'd show up on the existing policy
object, but they don't:
It seems I need to create a new variable assignment in order to access to those properties:
Any concerns here?
Polly is a . NET library that provides resilience and transient-fault handling capabilities. You can implement those capabilities by applying Polly policies such as Retry, Circuit Breaker, Bulkhead Isolation, Timeout, and Fallback.
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 so forth. It is a mature library that is almost synonymous with app resiliency.
With only a few lines of code, Polly can retry failed requests, cache previous responses, protect your resources, prevent you from making requests to broken services, terminate requests that are taking too long and return a default value when all else fails. It's also thread safe and works on sync and async calls.
No concerns. Configuring policies separate from their usage, and injecting them into sites of usage, is a common pattern which we use extensively in production.
All Polly policies are thread-safe and may be used across multiple independent call-sites concurrently.
Two kinds of Polly policy thread-safely maintain internal state across calls, to carry out their designed functions. This leads to specific (intended) effects if you share those policy instances across call sites.
CircuitBreaker
/ AdvancedCircuitBreaker
The raison-d'etre is to count and act according to success/fail metrics across calls placed through the policy. Each single policy instance maintains this state for itself internally.
The (intended) functional consequence of this is that if you share a CircuitBreakerPolicy
instance in multiple call sites, those multiple call sites will share circuit state, as discussed here.
Bulkhead
The raison-d'etre is to limit concurrency of calls placed through it. Each single BulkheadPolicy
instance maintains state internally to track that.
The (intended) functional consequence of this is that when you share a BulkheadPolicy
instance across call-sites, those call-sites share the bulkhead capacity between them.
BulkheadPolicy
instance across multiple call sites when you want call sites to share the bulkhead capacity between them. BulkheadPolicy
instance across multiple call sites when you want them to have independent bulkhead capacity. No other kind of Polly policy maintains internal state in the policy instance across executions.
.ExecuteAndCapture(...)
The result of an .ExecuteAndCapture(...)
call is not on the policy
in either of the cases in the question. In both cases (definition and execution in one statement; or separated), the result of the .ExecuteAndCapture(...)
call is a fresh PolicyResult
instance.
Each execution returns a fresh PolicyResult
instance. PolicyResult
is never stored as state on a policy instance (that would make policies not thread-safe and re-useable across call sites).
Change var
to the actual type (Policy
or PolicyResult
) in each code location, and this may be clearer to see.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With