Skip to main content

tower/circuit_breaker/
layer.rs

1use std::time::Duration;
2
3use super::{
4    policy::{CircuitPolicy, ConsecutiveFailures},
5    service::CircuitBreaker,
6};
7
8/// [`Layer`] that wraps services in a [`CircuitBreaker`].
9///
10/// Construct with [`CircuitBreakerLayer::new`] for the standard
11/// [`ConsecutiveFailures`] policy, or with [`CircuitBreakerLayer::with_policy`]
12/// to supply any custom [`CircuitPolicy`].
13///
14/// [`Layer`]: tower_layer::Layer
15#[derive(Clone, Debug)]
16pub struct CircuitBreakerLayer<P> {
17    policy: P,
18}
19
20impl CircuitBreakerLayer<ConsecutiveFailures> {
21    /// Create a layer using the built-in [`ConsecutiveFailures`] policy.
22    ///
23    /// - `failure_threshold`: consecutive failures before the circuit opens.
24    /// - `success_threshold`: fraction of probes (0.0–1.0) that must succeed
25    ///   during [`HalfOpen`][crate::circuit_breaker::CircuitStatus::HalfOpen]
26    ///   before the circuit closes again.
27    /// - `timeout`: how long to stay open before sending the first probe.
28    pub fn new(failure_threshold: usize, success_threshold: f64, timeout: Duration) -> Self {
29        Self {
30            policy: ConsecutiveFailures::new(failure_threshold, success_threshold, timeout),
31        }
32    }
33}
34
35impl<P: CircuitPolicy + Clone> CircuitBreakerLayer<P> {
36    /// Create a layer using a custom [`CircuitPolicy`].
37    ///
38    /// # Example
39    ///
40    /// ```rust,ignore
41    /// use tower::circuit_breaker::{CircuitBreakerLayer, ConsecutiveFailures};
42    /// use std::time::Duration;
43    ///
44    /// // Using the built-in policy explicitly:
45    /// let policy = ConsecutiveFailures::new(5, 0.8, Duration::from_secs(30));
46    /// let layer  = CircuitBreakerLayer::with_policy(policy);
47    ///
48    /// // Or bring your own:
49    /// let layer = CircuitBreakerLayer::with_policy(MyLatencyPolicy::new());
50    /// ```
51    pub fn with_policy(policy: P) -> Self {
52        Self { policy }
53    }
54}
55
56impl<S, P: CircuitPolicy + Clone> tower_layer::Layer<S> for CircuitBreakerLayer<P> {
57    type Service = CircuitBreaker<S, P>;
58
59    fn layer(&self, inner: S) -> Self::Service {
60        CircuitBreaker::new(inner, self.policy.clone())
61    }
62}