Skip to main content

do_over/
tower.rs

1
2use tower::Service;
3use std::task::{Context, Poll};
4use std::sync::Arc;
5use tokio::sync::Mutex;
6use crate::policy::Policy;
7
8pub struct DoOverService<S, P> {
9    inner: Arc<Mutex<S>>,
10    policy: P,
11}
12
13impl<S, P> DoOverService<S, P> {
14    pub fn new(inner: S, policy: P) -> Self {
15        Self {
16            inner: Arc::new(Mutex::new(inner)),
17            policy,
18        }
19    }
20}
21
22impl<S, P, Req, Res, Err> Service<Req> for DoOverService<S, P>
23where
24    S: Service<Req, Response = Res, Error = Err> + Send + 'static,
25    S::Future: Send,
26    P: Policy<Err> + Send + Sync + 'static + Clone,
27    Req: Send + Sync + Clone + 'static,
28    Res: Send + 'static,
29    Err: Send + 'static,
30{
31    type Response = Res;
32    type Error = Err;
33    type Future = futures::future::BoxFuture<'static, Result<Res, Err>>;
34
35    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
36        // Since we're using Arc<Mutex<S>>, we're always ready
37        Poll::Ready(Ok(()))
38    }
39
40    fn call(&mut self, req: Req) -> Self::Future {
41        let inner = Arc::clone(&self.inner);
42        let policy = self.policy.clone();
43        
44        Box::pin(async move {
45            policy.execute(|| async {
46                let mut svc = inner.lock().await;
47                svc.call(req.clone()).await
48            }).await
49        })
50    }
51}