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}