monolake_services/common/
timeout.rs1use std::time::Duration;
25
26use monoio::time::timeout;
27use service_async::{
28 layer::{layer_fn, FactoryLayer},
29 AsyncMakeService, MakeService, Param, Service,
30};
31
32#[derive(Clone)]
34pub struct TimeoutService<T> {
35 pub timeout: Duration,
36 pub inner: T,
37}
38
39#[derive(thiserror::Error, Debug)]
40pub enum TimeoutError<E> {
41 #[error("inner error: {0:?}")]
42 Inner(E),
43 #[error("timeout")]
44 Timeout,
45}
46
47impl<R, T: Service<R>> Service<R> for TimeoutService<T> {
48 type Response = T::Response;
49 type Error = TimeoutError<T::Error>;
50
51 async fn call(&self, req: R) -> Result<Self::Response, Self::Error> {
52 match timeout(self.timeout, self.inner.call(req)).await {
53 Ok(Ok(resp)) => Ok(resp),
54 Ok(Err(err)) => Err(TimeoutError::Inner(err)),
55 Err(_) => Err(TimeoutError::Timeout),
56 }
57 }
58}
59
60#[derive(Debug, Clone, Copy)]
61pub struct Timeout(pub Duration);
62
63impl<F> TimeoutService<F> {
64 pub fn layer<C>() -> impl FactoryLayer<C, F, Factory = Self>
65 where
66 C: Param<Timeout>,
67 {
68 layer_fn(|c: &C, inner| TimeoutService {
69 timeout: c.param().0,
70 inner,
71 })
72 }
73}
74
75impl<F: MakeService> MakeService for TimeoutService<F> {
76 type Service = TimeoutService<F::Service>;
77 type Error = F::Error;
78
79 fn make_via_ref(&self, old: Option<&Self::Service>) -> Result<Self::Service, Self::Error> {
80 Ok(TimeoutService {
81 timeout: self.timeout,
82 inner: self
83 .inner
84 .make_via_ref(old.map(|o| &o.inner))
85 .map_err(Into::into)?,
86 })
87 }
88}
89
90impl<F: AsyncMakeService> AsyncMakeService for TimeoutService<F> {
91 type Service = TimeoutService<F::Service>;
92 type Error = F::Error;
93
94 async fn make_via_ref(
95 &self,
96 old: Option<&Self::Service>,
97 ) -> Result<Self::Service, Self::Error> {
98 Ok(TimeoutService {
99 timeout: self.timeout,
100 inner: self
101 .inner
102 .make_via_ref(old.map(|o| &o.inner))
103 .await
104 .map_err(Into::into)?,
105 })
106 }
107}