Polly Roadmap - App-vNext/Polly GitHub Wiki

Polly Roadmap

ℹī¸ This documentation describes the previous Polly v7 API. If you are using the new v8 API, please refer to pollydocs.org.

The roadmap indicates currently envisaged or candidate development directions for Polly.

Community feedback on features you would like, or priorities, is welcome.

If you're interested in following and contributing to the development direction of Polly, join our public Slack channel for real-time discussion of ideas.

Medium priority

Refresh syntax

The number of overloads available to configure policies can cause confusion.

A mitigation could be splitting up the fluent syntax of step 2, policy configuration. Currently, all parameters of policy configuration (mandatory and optional) are configured in a single overload. Separating out the parameters (particularly optional ones) into postfix builder methods as below would reduce the overloads.

// Example syntax under consideration
var retryPolicy = Policy
  .Handle<FooException>()
  .RetryAsync(with => with
      .RetryCount(3)
      .DelayBeforeRetrying(...)
      .OnRetry(ex, timespan => ...);

Whatever syntax reconfiguration could be chosen, policies should probably remain immutable once used.

Rate-limit Policy

A policy to limit the number of calls placed through the policy per timespan. Useful when calling a third-party system which imposes a rate-limit on its API, provided that rate-limit is known. Perhaps taking a similar approach (with refinements) to something like Jack Leitch's RateGate.

Compare BulkheadPolicy. While BulkheadPolicy is a parallelism-throttle, RateLimitPolicy would be a serial throttle.

Note: A rate-limiting design of the RateGate kind, which 'holds back' already-executing hot Tasks or threads until it is their time/turn to proceed, is intrinsically vulnerable to memory bulges (all those waiting executions have to be held in memory) in high-volume scenarios where fresh requests consistently outstrip the permitted rate. Two possibilities to deal with this are co-operative demand control (aka back-pressure) and load-shedding.

In high-volume scenarios where you have control over the producers, co-operative demand control by back-pressure is recommended; Akka streams is a mature solution for this.

For those whose scenario is amenable to Rx, there may be the option of in-built operators such as throttle, buffer, sample and window.

A RateLimitPolicy in Polly could still be useful, particularly if we can provide options for configurable load-limits/load-shedding. Possibilities include:

  • a configurable upper-bound on the number of executions (across all threads) that are allowed to queue. (This would have nice symmetry with the queue on BulkheadPolicy.)
  • shedding actions which have been queuing longer than a configurable TimeSpan (which TimeoutPolicy already provides).

Discussion in our Slack channel around here also drew out the difference between being the rate-abiding or rate-imposing party. Being the rate-imposing party sounds as simple as rejecting excess calls immediately rather than allowing them to queue.

Honouring RetryAfter as an alternative to Rate-Limit Policy

Many Azure APIs impose a rate-limit on usage dependent on the pricing tier, eg CosmosDB, and many of the cognitive services.

If you are seeking a Rate-Limit policy in connection with these, be sure to explore the alternative of Retry policies honouring a 429 Retry-After response code. CosmosDB and many cognitive services APIs return 429 responses indicating when a request may be retried. Polly already offers WaitAndRetry overloads which can calculate the duration to wait based on the returned result (i.e. the Retry-After header in this case).

Lower priority at present

Consider moving handle-predicates to instance/interface-configuration style

The existing static Policy.Handle<FooException>(...) syntax returning concrete-class PolicyBuilder could be replaced with an instance-based style:

new PolicyBuilder()
    .Handle<FooException>()

returning an IPolicyBuilder interface.

The benefit would be easier unit-testing of policy building, as IPolicyBuilder can be mocked. The main use case is where handle-clauses (ie the exception types) or other aspects of policies are driven from external configuration. Unit-testing styles without mocking are possible, but more indirect. Note: This only affects unit-testing .Handle<> clauses; all fully-configured policies are already returned as interfaces and fully mockable.

Intellectually, this would be a good place for Polly to end up. Some challenges:

Inactive

not currently in line for active development (usually due to unavailable developer resource)

Emit events, aggregate metrics to dashboards

Old-ish proposal: PROPOSAL--Polly-eventing-and-metrics-architecture

Slack channel: Metrics slack channel

Github discussion: #326

With the number of resilience strategies now available from Polly v5, emitting Policy events/statistics could be valuable.

Timings to completion/failure of Policy executions is now available via Polly.Contrib.TimingPolicy.

Circuit-breaker customisation

Some user requests concern refining circuit-breaker behaviour:

  • refining the transition out of half-open state #239; #254

We could add a CustomCircuitBreaker(ICircuitController myCustomController) to open up circuit-breaker customisation.

Getting involved

Comment on this roadmap here

Expressions of interest in developing any of the above functionality welcome! (for major features, contact the Polly team first to avoid duplication of effort). Some issues are also marked as 'up-for-grabs' at any time, in the Issues list. See also the notes for contributors!

Status

The roadmap is published for transparency and to solicit community input, but is by its nature indicative and subject to change: proposed features may be more difficult to implement than envisaged, or may be down-prioritised as we continue to seek the balance for the library between power and simplicity.

Features delivered from previous Roadmaps

Forthcoming in v8: #748: Performance improvements (major reduction in allocations); ability to pass input parameters to executions without using a closure

November 2019: Concurrent methods on PolicyRegistry

September 2019: New jitter formula (via Polly.Contrib.WaitAndRetry)

September 2019: Distributed Circuit Breaker (via Polly.Contrib.AzureFunctions.CircuitBreaker)

February 2019: Clarified sync/async policy separation. Added Source Link support.

February 2019: custom policies. Polly.Contrib.

April 2018: integration to IHttpClientFactory for ASPNET Core 2.1

February 2018: dynamic reconfiguration during running

November 2017: numerous small enhancements including durations to wait in wait and retry, based on error response.

October 2017: CachePolicy (thanks to @seanfarrow for much contribution to the thinking).

June 2017: PolicyRegistry (thanks to @ankitbko); interfaces.

May 2017: Share rich information between execution and control delegates (blog)

February 2017: NoOp Policy (thanks to @lakario)

December 2016: Polly v5.0.3 RTM:

  • Full .NET Standard 1.0 compatibility
  • Bulkhead policy
  • Timeout policy (including walking away from executions with no in-built timeout)
  • Fallback policy
  • PolicyWrap,
  • PolicyKeys and ContextData
  • Rationalised .NET40 async support

October 2016: Polly v5.0-alpha, with four new policies: Bulkhead, Timeout, Fallback, and PolicyWrap

July 2016: .NET Core 1.0 RTM support; .NET Standard 1.0 support

June 2016: Policies to handle return values

June 2016: Polly.Net40Async

April 2016: Advanced Circuit Breaker

Mar 2016: Full ContextualPolicy support

Feb 2016: Manual control and public state for circuit breaker, for health/performance monitoring

Jan 2016: Full async support.