1use core::convert::Infallible;
4use core::future::*;
5use core::pin::Pin;
6
7use axum::serve::*;
8use tower::Service;
9
10use crate::res::*;
11use crate::req::*;
12use super::*;
13
14type F1 = Pin<Box<dyn Future<Output = ()> + Send>>;
15type Ca<S, State> = WithGracefulShutdown<AxumRouter<State>, S, F1>;
16
17#[repr(transparent)]
19#[allow(missing_debug_implementations)]
20pub struct CatalyzedApp<S, State = ()>(Ca<S, State>) where
21 State: Clone + Send + Sync + 'static,
22 AxumRouter<State>: for<'a> Service<IncomingStream<'a>, Error = Infallible, Response = S> + Send + 'static,
23 for<'a> <AxumRouter<State> as Service<IncomingStream<'a>>>::Future: Send,
24 S: Service<RawRequest, Response = RawResponse, Error = Infallible> + Clone + Send + 'static,
25 S::Future: Send;
26impl<S, State> IntoFuture for CatalyzedApp<S, State> where
27 State: Clone + Send + Sync + 'static,
28 AxumRouter<State>: for<'a> Service<IncomingStream<'a>, Error = Infallible, Response = S> + Send + 'static,
29 for<'a> <AxumRouter<State> as Service<IncomingStream<'a>>>::Future: Send,
30 S: Service<RawRequest, Response = RawResponse, Error = Infallible> + Clone + Send + 'static,
31 S::Future: Send, {
32 type Output = <Ca<S, State> as IntoFuture>::Output;
33 type IntoFuture = <Ca<S, State> as IntoFuture>::IntoFuture;
34 #[inline] fn into_future(self) -> Self::IntoFuture { self.0.into_future() } }
35impl<S, State> App<State> where
36 State: Clone + Send + Sync + 'static,
37 AxumRouter<State>: for<'a> Service<IncomingStream<'a>, Error = Infallible, Response = S> + Send + 'static,
38 for<'a> <AxumRouter<State> as Service<IncomingStream<'a>>>::Future: Send,
39 S: Service<RawRequest, Response = RawResponse, Error = Infallible> + Clone + Send + 'static,
40 S::Future: Send,
41{
42 pub async fn launch(self) -> Result<CatalyzedApp<S, State>> {
46 let addr = self.address.ok_or(CatalyzerError::NoAddress)?;
47 let tcp = tokio::net::TcpListener::bind(addr).await?;
48 let app = axum::serve(tcp, self.router);
49 Ok(CatalyzedApp(app.with_graceful_shutdown(signal_handler())))
50 }
51}
52
53#[inline]
54fn signal_handler() -> Pin<Box<dyn Future<Output = ()> + Send>> {
55 use super::runtime::signals::*;
56 Box::pin(async { tokio::select! {
57 _ = ctrl_c() => {},
58 _ = term() => {},
59 } })
60}