tower_retry_plus/layer.rs
1use crate::{Retry, RetryConfig};
2use std::sync::Arc;
3use tower::Layer;
4
5/// A Tower [`Layer`] that applies retry logic to a service.
6///
7/// This layer wraps a service with retry middleware that automatically
8/// retries failed requests according to the configured policy.
9///
10/// # Examples
11///
12/// ```
13/// use tower_retry_plus::RetryConfig;
14/// use tower::ServiceBuilder;
15/// use std::time::Duration;
16///
17/// # #[derive(Debug, Clone)]
18/// # struct MyError;
19/// # async fn example() {
20/// let retry_layer: tower_retry_plus::RetryLayer<MyError> = RetryConfig::builder()
21/// .max_attempts(5)
22/// .exponential_backoff(Duration::from_millis(100))
23/// .build()
24/// .layer();
25///
26/// let service = ServiceBuilder::new()
27/// .layer(retry_layer)
28/// .service(my_service());
29/// # }
30/// # fn my_service() -> impl tower::Service<String, Response = String, Error = MyError> {
31/// # tower::service_fn(|req: String| async move { Ok::<_, MyError>(req) })
32/// # }
33/// ```
34#[derive(Clone)]
35pub struct RetryLayer<E> {
36 config: Arc<RetryConfig<E>>,
37}
38
39impl<E> RetryLayer<E> {
40 /// Creates a new `RetryLayer` with the given configuration.
41 pub fn new(config: RetryConfig<E>) -> Self {
42 Self {
43 config: Arc::new(config),
44 }
45 }
46}
47
48impl<S, E> Layer<S> for RetryLayer<E>
49where
50 E: Clone,
51{
52 type Service = Retry<S, E>;
53
54 fn layer(&self, service: S) -> Self::Service {
55 Retry::new(service, Arc::clone(&self.config))
56 }
57}