tower_resilience_fallback/layer.rs
1//! Tower layer for fallback.
2
3use crate::config::{FallbackConfig, FallbackConfigBuilder};
4use crate::Fallback;
5use std::sync::Arc;
6use tower::layer::Layer;
7
8/// A Tower layer that applies fallback behavior to a service.
9///
10/// See the [module-level documentation](crate) for usage examples.
11pub struct FallbackLayer<Req, Res, E> {
12 config: Arc<FallbackConfig<Req, Res, E>>,
13}
14
15impl<Req, Res, E> FallbackLayer<Req, Res, E> {
16 /// Creates a new fallback layer from the given configuration.
17 pub(crate) fn new(config: FallbackConfig<Req, Res, E>) -> Self {
18 Self {
19 config: Arc::new(config),
20 }
21 }
22
23 /// Creates a new builder for configuring a fallback layer.
24 pub fn builder() -> FallbackConfigBuilder<Req, Res, E> {
25 FallbackConfigBuilder::new()
26 }
27
28 /// Creates a fallback layer that generates a value using a function.
29 ///
30 /// Unlike [`value`](Self::value), this doesn't require `Res: Clone` since
31 /// the function generates a fresh value for each fallback.
32 ///
33 /// # Example
34 ///
35 /// ```rust
36 /// use tower_resilience_fallback::FallbackLayer;
37 ///
38 /// # #[derive(Debug)]
39 /// # struct MyError;
40 /// # struct MyResponse { data: Vec<u8> } // No Clone needed!
41 /// let layer = FallbackLayer::<String, MyResponse, MyError>::value_fn(|| {
42 /// MyResponse { data: vec![0; 1024] }
43 /// });
44 /// ```
45 pub fn value_fn<F>(f: F) -> Self
46 where
47 F: Fn() -> Res + Send + Sync + 'static,
48 {
49 FallbackConfigBuilder::new().value_fn(f).build()
50 }
51}
52
53// Convenience constructors for common patterns
54impl<Req, Res, E> FallbackLayer<Req, Res, E>
55where
56 Res: Clone,
57{
58 /// Creates a fallback layer that returns a static value on failure.
59 ///
60 /// Note: This requires `Res: Clone`. If your response type doesn't implement
61 /// Clone, use [`value_fn`](Self::value_fn) instead.
62 ///
63 /// # Example
64 ///
65 /// ```rust
66 /// use tower_resilience_fallback::FallbackLayer;
67 ///
68 /// # #[derive(Debug, Clone)]
69 /// # struct MyError;
70 /// let layer = FallbackLayer::<String, String, MyError>::value("default".to_string());
71 /// ```
72 pub fn value(value: Res) -> Self {
73 FallbackConfigBuilder::new().value(value).build()
74 }
75
76 /// Creates a fallback layer that computes a response from the error.
77 ///
78 /// # Example
79 ///
80 /// ```rust
81 /// use tower_resilience_fallback::FallbackLayer;
82 ///
83 /// # #[derive(Debug, Clone)]
84 /// # struct MyError { msg: String }
85 /// let layer = FallbackLayer::<String, String, MyError>::from_error(|e| {
86 /// format!("Error: {}", e.msg)
87 /// });
88 /// ```
89 pub fn from_error<F>(f: F) -> Self
90 where
91 F: Fn(&E) -> Res + Send + Sync + 'static,
92 {
93 FallbackConfigBuilder::new().from_error(f).build()
94 }
95
96 /// Creates a fallback layer that computes a response from request and error.
97 ///
98 /// # Example
99 ///
100 /// ```rust
101 /// use tower_resilience_fallback::FallbackLayer;
102 ///
103 /// # #[derive(Debug, Clone)]
104 /// # struct MyError;
105 /// let layer = FallbackLayer::<String, String, MyError>::from_request_error(|req, _err| {
106 /// format!("Fallback for request: {}", req)
107 /// });
108 /// ```
109 pub fn from_request_error<F>(f: F) -> Self
110 where
111 F: Fn(&Req, &E) -> Res + Send + Sync + 'static,
112 {
113 FallbackConfigBuilder::new().from_request_error(f).build()
114 }
115
116 /// Creates a fallback layer that routes to a backup service.
117 ///
118 /// # Example
119 ///
120 /// ```rust
121 /// use tower_resilience_fallback::FallbackLayer;
122 ///
123 /// # #[derive(Debug, Clone)]
124 /// # struct MyError;
125 /// let layer = FallbackLayer::<String, String, MyError>::service(|req: String| async move {
126 /// Ok::<_, MyError>(format!("backup: {}", req))
127 /// });
128 /// ```
129 pub fn service<S, Fut>(service: S) -> Self
130 where
131 S: Fn(Req) -> Fut + Send + Sync + 'static,
132 Fut: std::future::Future<Output = Result<Res, E>> + Send + 'static,
133 {
134 FallbackConfigBuilder::new().service(service).build()
135 }
136
137 /// Creates a fallback layer that transforms errors.
138 ///
139 /// Note: This still returns an error, just a transformed one.
140 ///
141 /// # Example
142 ///
143 /// ```rust
144 /// use tower_resilience_fallback::FallbackLayer;
145 ///
146 /// # #[derive(Debug, Clone)]
147 /// # struct MyError { code: u32 }
148 /// let layer = FallbackLayer::<String, String, MyError>::exception(|e| {
149 /// MyError { code: 500 }
150 /// });
151 /// ```
152 pub fn exception<F>(f: F) -> Self
153 where
154 F: Fn(E) -> E + Send + Sync + 'static,
155 {
156 FallbackConfigBuilder::new().exception(f).build()
157 }
158}
159
160impl<Req, Res, E> Clone for FallbackLayer<Req, Res, E>
161where
162 Res: Clone,
163{
164 fn clone(&self) -> Self {
165 Self {
166 config: Arc::clone(&self.config),
167 }
168 }
169}
170
171impl<S, Req, Res, E> Layer<S> for FallbackLayer<Req, Res, E>
172where
173 Res: Clone,
174{
175 type Service = Fallback<S, Req, Res, E>;
176
177 fn layer(&self, service: S) -> Self::Service {
178 Fallback::new(service, Arc::clone(&self.config))
179 }
180}