Skip to main content

tower_resilience_adaptive/
layer.rs

1//! Layer implementation for adaptive concurrency limiting.
2
3use crate::{AdaptiveService, Algorithm, ConcurrencyAlgorithm};
4use std::sync::Arc;
5use tower_layer::Layer;
6
7/// A Tower layer that applies adaptive concurrency limiting.
8///
9/// This layer dynamically adjusts the number of concurrent requests based
10/// on observed latency and error rates, using algorithms like AIMD or Vegas.
11///
12/// # Example
13///
14/// ```rust,no_run
15/// use tower_resilience_adaptive::{AdaptiveLimiterLayer, Aimd};
16/// use std::time::Duration;
17///
18/// let layer = AdaptiveLimiterLayer::new(
19///     Aimd::builder()
20///         .initial_limit(10)
21///         .latency_threshold(Duration::from_millis(100))
22///         .build()
23/// );
24/// ```
25pub struct AdaptiveLimiterLayer<A> {
26    algorithm: Arc<A>,
27}
28
29impl<A> AdaptiveLimiterLayer<A>
30where
31    A: ConcurrencyAlgorithm,
32{
33    /// Create a new adaptive limiter layer with the given algorithm.
34    pub fn new(algorithm: A) -> Self {
35        Self {
36            algorithm: Arc::new(algorithm),
37        }
38    }
39
40    /// Create a builder for configuring the layer.
41    pub fn builder() -> AdaptiveLimiterLayerBuilder {
42        AdaptiveLimiterLayerBuilder::new()
43    }
44}
45
46impl<A> Clone for AdaptiveLimiterLayer<A> {
47    fn clone(&self) -> Self {
48        Self {
49            algorithm: Arc::clone(&self.algorithm),
50        }
51    }
52}
53
54impl<S, A> Layer<S> for AdaptiveLimiterLayer<A>
55where
56    A: ConcurrencyAlgorithm + 'static,
57{
58    type Service = AdaptiveService<S, A>;
59
60    fn layer(&self, service: S) -> Self::Service {
61        AdaptiveService::new(service, Arc::clone(&self.algorithm))
62    }
63}
64
65/// Builder for configuring an adaptive limiter layer.
66pub struct AdaptiveLimiterLayerBuilder {
67    _private: (),
68}
69
70impl AdaptiveLimiterLayerBuilder {
71    fn new() -> Self {
72        Self { _private: () }
73    }
74
75    /// Use the AIMD algorithm.
76    pub fn aimd(self) -> crate::AimdBuilder {
77        crate::Aimd::builder()
78    }
79
80    /// Use the Vegas algorithm.
81    pub fn vegas(self) -> crate::VegasBuilder {
82        crate::Vegas::builder()
83    }
84}
85
86/// Extension trait for building layers from algorithm builders.
87pub trait IntoLayer {
88    /// The algorithm type produced.
89    type Algorithm: ConcurrencyAlgorithm;
90
91    /// Build the layer.
92    fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm>;
93}
94
95impl IntoLayer for crate::Aimd {
96    type Algorithm = crate::Aimd;
97
98    fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm> {
99        AdaptiveLimiterLayer::new(self)
100    }
101}
102
103impl IntoLayer for crate::Vegas {
104    type Algorithm = crate::Vegas;
105
106    fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm> {
107        AdaptiveLimiterLayer::new(self)
108    }
109}
110
111impl IntoLayer for Algorithm {
112    type Algorithm = Algorithm;
113
114    fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm> {
115        AdaptiveLimiterLayer::new(self)
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122    use crate::Aimd;
123    use std::time::Duration;
124
125    #[test]
126    fn test_layer_creation() {
127        let algorithm = Aimd::builder()
128            .initial_limit(10)
129            .latency_threshold(Duration::from_millis(100))
130            .build();
131        let layer = AdaptiveLimiterLayer::new(algorithm);
132        let _ = layer.clone();
133    }
134
135    #[test]
136    fn test_into_layer() {
137        let layer = Aimd::builder().initial_limit(10).build().into_layer();
138        let _ = layer.clone();
139    }
140}