use processmanager::*;
use std::{sync::Arc, time::Duration};
use tokio::time::{interval, sleep};
struct Worker {
id: usize,
guard: Arc<RuntimeGuard>,
}
impl Worker {
fn new(id: usize) -> Self {
Self {
id,
guard: Arc::new(RuntimeGuard::default()),
}
}
}
impl Runnable for Worker {
fn process_start(&self) -> ProcFuture<'_> {
let id = self.id;
let guard = self.guard.clone();
Box::pin(async move {
let ticker = guard.runtime_ticker().await;
let mut beat = interval(Duration::from_secs(1));
loop {
match ticker.tick(beat.tick()).await {
ProcessOperation::Next(_) => println!("worker-{id}: heartbeat"),
ProcessOperation::Control(RuntimeControlMessage::Reload) => {
println!("worker-{id}: received *reload*")
}
ProcessOperation::Control(RuntimeControlMessage::Shutdown) => {
println!("worker-{id}: shutting down");
break;
}
ProcessOperation::Control(_) => continue,
}
}
Ok(())
})
}
fn process_handle(&self) -> Arc<dyn ProcessControlHandler> {
self.guard.handle()
}
}
#[tokio::main]
async fn main() {
let mgr = ProcessManagerBuilder::default()
.pre_insert(Worker::new(0))
.build();
let mgr: Arc<ProcessManager> = Arc::new(mgr);
let mgr_clone = Arc::clone(&mgr);
tokio::spawn(async move {
mgr_clone
.process_start()
.await
.expect("manager encountered an error");
});
let handle = mgr.process_handle();
println!("==> main: sleeping 3 s before adding worker-1");
sleep(Duration::from_secs(3)).await;
println!("==> main: adding worker-1");
mgr.add(Worker::new(1));
println!("==> main: sleeping 2 s");
sleep(Duration::from_secs(2)).await;
println!("==> main: adding worker-2");
mgr.add(Worker::new(2));
println!("==> main: running 5 s before global shutdown");
sleep(Duration::from_secs(5)).await;
println!("==> main: initiating graceful shutdown");
handle.shutdown().await;
sleep(Duration::from_secs(1)).await;
}