#[macro_use] extern crate rocket; mod argp; mod err; mod procres; use qsu::{ argp::ArgParser, rt::{InitCtx, RocketServiceHandler, RunEnv, SrvAppRt, SvcEvt, TermCtx} }; use tokio::sync::mpsc; use rocket::{Build, Ignite, Rocket}; use err::Error; use procres::ProcRes; struct MyService { rx: mpsc::UnboundedReceiver } #[qsu::async_trait] impl RocketServiceHandler for MyService { type AppErr = Error; async fn init( &mut self, ictx: InitCtx ) -> Result>, Self::AppErr> { tracing::trace!("Running init()"); let mut rockets = vec![]; ictx.report(Some("Building a rocket!".into())); let rocket = rocket::build().mount("/", routes![index]); ictx.report(Some("Pushing a rocket".into())); rockets.push(rocket); Ok(rockets) } #[allow(clippy::redundant_pub_crate)] async fn run( &mut self, rockets: Vec>, _re: &RunEnv ) -> Result<(), Self::AppErr> { for rocket in rockets { tokio::task::spawn(async { rocket.launch().await.unwrap(); }); } loop { tokio::select! { evt = self.rx.recv() => { match evt { Some(SvcEvt::Shutdown(_)) => { tracing::info!("The service subsystem requested that the application shut down"); break; } Some(SvcEvt::ReloadConf) => { tracing::info!("The service subsystem requested that application reload configuration"); } _ => { } } } } } Ok(()) } async fn shutdown(&mut self, tctx: TermCtx) -> Result<(), Self::AppErr> { tctx.report(Some(format!("Entered {}", "shutdown").into())); tracing::trace!("Running shutdown()"); Ok(()) } } fn main() -> ProcRes { // In the future we'll be able to use Try to implement support for implicit // conversion to ProcRes from a Result using `?`, but for now use this hack. ProcRes::into(main2().into()) } fn main2() -> Result<(), Error> { // Derive default service name from executable name. let svcname = qsu::default_service_name() .expect("Unable to determine default service name"); let bldr = Box::new(|| { let (tx, rx) = mpsc::unbounded_channel(); let svcevt_handler = Box::new(move |msg| { // Just foward messages to runtime handler tx.send(msg).unwrap(); }); let rt_handler = Box::new(MyService { rx }); SrvAppRt::Rocket { svcevt_handler, rt_handler } }); // Parse, and process, command line arguments. let mut argsproc = argp::AppArgsProc { bldr }; let ap = ArgParser::new(&svcname, &mut argsproc).regsvc_proc(|mut regsvc| { // Hard-code this as a network service application. regsvc.netservice_ref(); // Set description, but only if it hasn't been set already (presumably // via the command line). if regsvc.description.is_none() { regsvc.description_ref("A simple Rocket server that logs requests"); } regsvc }); ap.proc()?; Ok(()) } #[get("/")] fn index() -> &'static str { log::error!("error"); log::warn!("warn"); log::info!("info"); log::debug!("debug"); log::trace!("trace"); tracing::error!("error"); tracing::warn!("warn"); tracing::info!("info"); tracing::debug!("debug"); tracing::trace!("trace"); "Hello, world!" } // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :