tower_retry/policy.rs
1use std::future::Future;
2
3/// A "retry policy" to classify if a request should be retried.
4///
5/// # Example
6///
7/// ```
8/// use tower_retry::Policy;
9/// use futures_util::future;
10///
11/// type Req = String;
12/// type Res = String;
13///
14/// struct Attempts(usize);
15///
16/// impl<E> Policy<Req, Res, E> for Attempts {
17/// type Future = future::Ready<Self>;
18///
19/// fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future> {
20/// match result {
21/// Ok(_) => {
22/// // Treat all `Response`s as success,
23/// // so don't retry...
24/// None
25/// },
26/// Err(_) => {
27/// // Treat all errors as failures...
28/// // But we limit the number of attempts...
29/// if self.0 > 0 {
30/// // Try again!
31/// Some(future::ready(Attempts(self.0 - 1)))
32/// } else {
33/// // Used all our attempts, no retry...
34/// None
35/// }
36/// }
37/// }
38/// }
39///
40/// fn clone_request(&self, req: &Req) -> Option<Req> {
41/// Some(req.clone())
42/// }
43/// }
44/// ```
45pub trait Policy<Req, Res, E>: Sized {
46 /// The `Future` type returned by `Policy::retry()`.
47 type Future: Future<Output = Self>;
48 /// Check the policy if a certain request should be retried.
49 ///
50 /// This method is passed a reference to the original request, and either
51 /// the `Service::Response` or `Service::Error` from the inner service.
52 ///
53 /// If the request should **not** be retried, return `None`.
54 ///
55 /// If the request *should* be retried, return `Some` future of a new
56 /// policy that would apply for the next request attempt.
57 fn retry(&self, req: &Req, result: Result<&Res, &E>) -> Option<Self::Future>;
58 /// Tries to clone a request before being passed to the inner service.
59 ///
60 /// If the request cannot be cloned, return `None`.
61 fn clone_request(&self, req: &Req) -> Option<Req>;
62}