mod argp;
mod err;
mod procres;
use std::{sync::mpsc, time::Duration};
use qsu::{
argp::ArgParser,
rt::{InitCtx, RunEnv, ServiceHandler, SrvAppRt, SvcEvt, TermCtx}
};
use err::Error;
use procres::ProcRes;
struct InitData {
name: String,
value: u32
}
struct TermData {
name: String,
value: u32
}
struct AnotherTermData {
name: String,
value: u32
}
struct MyService {
rx: mpsc::Receiver<SvcEvt>
}
impl ServiceHandler for MyService {
type AppErr = Error;
fn init(&mut self, ictx: &mut InitCtx) -> Result<(), Self::AppErr> {
ictx.report(Some("Entered init"));
let id = ictx.take::<InitData>().unwrap();
assert_eq!(id.name, "hello");
assert_eq!(id.value, 42);
log::info!("init passthrough name={}, value={}", id.name, id.value);
let atd = AnotherTermData {
name: "extra bye".to_string(),
value: 23
};
ictx.term_passthrough(atd);
Ok(())
}
fn run(&mut self, _re: &RunEnv) -> Result<(), Self::AppErr> {
log::info!("Wait for termination event for up to 8 seconds ..");
loop {
let Ok(evt) = self.rx.recv_timeout(Duration::from_secs(8)) else {
break;
};
if let SvcEvt::Shutdown(_) = evt {
break;
}
}
Ok(())
}
fn shutdown(&mut self, tctx: &mut TermCtx) -> Result<(), Self::AppErr> {
tctx.report(Some("Entered shutdown"));
log::trace!("Running shutdown()");
let td = tctx.take::<TermData>().unwrap();
assert_eq!(td.name, "bye");
assert_eq!(td.value, 17);
log::info!("term passthrough name={}, value={}", td.name, td.value);
let atd = tctx.take::<AnotherTermData>().unwrap();
assert_eq!(atd.name, "extra bye");
assert_eq!(atd.value, 23);
log::info!(
"another term passthrough name={}, value={}",
atd.name,
atd.value
);
Ok(())
}
}
fn main() -> ProcRes {
ProcRes::into(main2().into())
}
fn main2() -> Result<(), Error> {
let svcname = qsu::default_service_name()
.expect("Unable to determine default service name");
let bldr = Box::new(|| {
let (tx, rx) = mpsc::channel();
SrvAppRt::Sync {
svcevt_handler: Box::new(move |msg| {
tx.send(msg).unwrap();
}),
rt_handler: Box::new(MyService { rx })
}
});
let id = InitData {
name: String::from("hello"),
value: 42
};
let td = TermData {
name: String::from("bye"),
value: 17
};
let mut argsproc = argp::AppArgsProc { bldr };
let ap = ArgParser::new(&svcname, &mut argsproc)
.runsvc_proc(|rctx| rctx.init_passthrough(id).term_passthrough(td))
.regsvc_proc(|mut regsvc| {
if regsvc.description.is_none() {
regsvc
.description_ref("A sync server that says hello every 30 seconds");
}
regsvc
});
ap.proc()?;
Ok(())
}