use bus::ExampleBus;
use lifeline::{assert_completes, assert_times_out, prelude::*};
use lifeline::{Receiver, Sender};
use message::{DomainShutdown, MainRecv, MainShutdown};
use service::MainService;
use simple_logger::SimpleLogger;
#[tokio::main]
pub async fn main() -> anyhow::Result<()> {
SimpleLogger::new().init().expect("log init failed");
let bus = ExampleBus::default();
let _service = MainService::spawn(&bus)?;
let mut tx = bus.tx::<MainRecv>()?;
let mut tx_domain_shutdown = bus.tx::<DomainShutdown>()?;
let mut rx_main_shutdown = bus.rx::<MainShutdown>()?;
drop(bus);
tx.send(MainRecv::Hello).await?;
tx_domain_shutdown.send(DomainShutdown {}).await?;
assert_times_out!(async { rx_main_shutdown.recv().await });
tx.send(MainRecv::Goodbye).await?;
assert_completes!(async {
let msg = rx_main_shutdown.recv().await;
assert_eq!(Some(MainShutdown {}), msg);
});
println!("All done.");
Ok(())
}
mod message {
#[derive(Debug, Clone)]
pub enum MainRecv {
Hello,
Goodbye,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MainShutdown;
#[derive(Debug, Clone)]
pub struct DomainShutdown;
#[derive(Debug, Default, Clone)]
pub struct MainEventBarrier;
}
mod bus {
use crate::message::{DomainShutdown, MainEventBarrier, MainRecv, MainShutdown};
use lifeline::prelude::*;
use postage::barrier;
use postage::mpsc;
lifeline_bus!(pub struct ExampleBus);
impl Message<ExampleBus> for MainRecv {
type Channel = mpsc::Sender<Self>;
}
impl Message<ExampleBus> for DomainShutdown {
type Channel = mpsc::Sender<Self>;
}
impl Message<ExampleBus> for MainShutdown {
type Channel = mpsc::Sender<Self>;
}
impl Message<ExampleBus> for MainEventBarrier {
type Channel = barrier::Sender;
}
}
mod service {
use super::bus::ExampleBus;
use crate::message::{DomainShutdown, MainEventBarrier, MainRecv, MainShutdown};
use lifeline::prelude::*;
use postage::{sink::Sink, stream::Stream};
pub struct MainService {
_greet: Lifeline,
_shutdown: Lifeline,
}
impl Service for MainService {
type Bus = ExampleBus;
type Lifeline = anyhow::Result<Self>;
fn spawn(bus: &Self::Bus) -> Self::Lifeline {
let _greet = {
let mut rx = bus.rx::<MainRecv>()?;
let mut tx_barrier = bus.tx::<MainEventBarrier>()?;
Self::try_task("greet", async move {
while let Some(recv) = rx.recv().await {
if let MainRecv::Goodbye = recv {
break;
}
}
tx_barrier.send(()).await?;
Ok(())
})
};
let _shutdown = {
let mut rx_domain_shutdown = bus.rx::<DomainShutdown>()?;
let mut rx_barrier = bus.rx::<MainEventBarrier>()?;
let mut tx_main_shutdown = bus.tx::<MainShutdown>()?;
Self::try_task("shutdown", async move {
if let Some(_shutdown) = rx_domain_shutdown.recv().await {
rx_barrier.recv().await;
tx_main_shutdown.send(MainShutdown {}).await.ok();
}
Ok(())
})
};
Ok(Self { _greet, _shutdown })
}
}
}