Skip to main content

catalyzer/app/
launch.rs

1//! 
2
3use 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/// A Catalyzed application that is ready to be launched.
18#[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    /// Catalyzes the application and launches it.
43    /// 
44    /// This should be the last method called on the [`App`](crate::App) instance.
45    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}