Skip to main content

CircuitPolicy

Trait CircuitPolicy 

Source
pub trait CircuitPolicy {
    // Required methods
    fn on_success(&mut self) -> bool;
    fn on_failure(&mut self) -> bool;
    fn should_probe(&self) -> bool;
    fn on_half_open(&mut self);
}
Available on crate feature circuit-breaker only.
Expand description

Determines when a CircuitBreaker should open, probe, and close.

Implement this trait to create custom circuit-breaking strategies — for example latency-based triggers, error-rate thresholds, or a manual operator-driven switch. The built-in ConsecutiveFailures policy is a good starting point for most use cases.

§Thread safety

CircuitPolicy does not require Send or Sync as supertraits, so single-threaded or !Send implementations are valid. However, because the policy is stored inside Arc<Mutex<…>> within CircuitBreaker, the compiler will automatically require P: Send whenever CircuitBreaker<S, P> is sent across threads (e.g. handed to tokio::spawn or used with a multi-threaded runtime). P: Sync is not needed — Mutex provides the necessary exclusion.

In practice, any policy that holds only owned data will be Send automatically. If you store a raw pointer or Rc in your policy, it will not be usable in a multi-threaded context — the compiler will tell you so at the call site.

§Relationship to [tower::retry::budget]

Budget governs retry worthiness: it caps the ratio of retried requests to original requests, preventing retry amplification. A circuit breaker governs traffic admission: it gates all requests (including first attempts) when a backend is known to be unhealthy.

The two compose naturally:

  • A budget limits how aggressively clients retry individual requests.
  • A circuit breaker stops all traffic once failure is systemic, giving the backend time to recover without being drowned in retried load.

Using a circuit breaker without a budget still exposes you to retry amplification from layers above; the combination of both provides full protection against retry storms.

┌──────────────────────────────────────┐
│           ServiceBuilder             │
│  .layer(CircuitBreakerLayer::…)  ◄── gates all traffic when open
│  .layer(RetryLayer::new(policy)) ◄── budget inside policy caps retries
│  .service_fn(my_backend)             │
└──────────────────────────────────────┘

Required Methods§

Source

fn on_success(&mut self) -> bool

Called after a successful response from the inner service.

Return true to signal that the circuit should close. This is acted upon only while the circuit is HalfOpen; returning true from a Closed state is a no-op.

Source

fn on_failure(&mut self) -> bool

Called after a failed response from the inner service.

Return true to signal that the circuit should open. This is acted upon when the circuit is Closed.

Any failure while the circuit is HalfOpen always reopens it, regardless of the return value — the probe failed, so the backend is not yet ready.

Source

fn should_probe(&self) -> bool

Called while the circuit is Open.

Return true to allow a probe request through (transitions the circuit to HalfOpen).

Source

fn on_half_open(&mut self)

Called immediately after the circuit transitions to HalfOpen.

Use this hook to reset per-window counters so that the recovery success rate is measured only from post-recovery probes, not from stale pre-outage history.

Implementors§