use tower::Service;
use std::task::{Context, Poll};
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::policy::Policy;
pub struct DoOverService<S, P> {
inner: Arc<Mutex<S>>,
policy: P,
}
impl<S, P> DoOverService<S, P> {
pub fn new(inner: S, policy: P) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
policy,
}
}
}
impl<S, P, Req, Res, Err> Service<Req> for DoOverService<S, P>
where
S: Service<Req, Response = Res, Error = Err> + Send + 'static,
S::Future: Send,
P: Policy<Err> + Send + Sync + 'static + Clone,
Req: Send + Sync + Clone + 'static,
Res: Send + 'static,
Err: Send + 'static,
{
type Response = Res;
type Error = Err;
type Future = futures::future::BoxFuture<'static, Result<Res, Err>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Req) -> Self::Future {
let inner = Arc::clone(&self.inner);
let policy = self.policy.clone();
Box::pin(async move {
policy.execute(|| async {
let mut svc = inner.lock().await;
svc.call(req.clone()).await
}).await
})
}
}