//! Simple service that does nothing other than log/trace every N seconds. mod argp; mod err; mod procres; use std::time::{Duration, Instant}; use qsu::{ argp::ArgParser, rt::{ InitCtx, RunEnv, SrvAppRt, SvcEvt, SvcEvtReader, TermCtx, TokioServiceHandler } }; use err::Error; use procres::ProcRes; struct MyService {} #[qsu::async_trait] impl TokioServiceHandler for MyService { async fn init(&mut self, ictx: InitCtx) -> Result<(), qsu::AppErr> { ictx.report(Some("Entered init".into())); tracing::trace!("Running init()"); Ok(()) } async fn run( &mut self, _re: &RunEnv, mut set: SvcEvtReader ) -> Result<(), qsu::AppErr> { const SECS: u64 = 30; let mut last_dump = Instant::now() - Duration::from_secs(SECS); loop { if Instant::now() - last_dump > Duration::from_secs(SECS) { 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"); last_dump = Instant::now(); } tokio::select! { _ = tokio::time::sleep(std::time::Duration::from_secs(1)) => { continue; } evt = set.arecv() => { match evt { Some(SvcEvt::Shutdown) => { tracing::info!("The service subsystem requested that the application shut down"); break; } Some(SvcEvt::Terminate) => { tracing::info!( "The service subsystem requested that the application terminate" ); break; } Some(SvcEvt::ReloadConf) => { tracing::info!("The service subsystem requested that application reload configuration"); } _ => { } } } } } Ok(()) } async fn shutdown(&mut self, tctx: TermCtx) -> Result<(), qsu::AppErr> { tctx.report(Some(("Entered shutdown".to_string()).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 creator = || { let handler = Box::new(MyService {}); SrvAppRt::Tokio(None, handler) }; // Parse, and process, command line arguments. let mut argsproc = argp::AppArgsProc { bldr: Box::new(creator) }; let ap = ArgParser::new(&svcname, &mut argsproc); ap.proc()?; Ok(()) } // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :