#![deny(missing_docs)]
pub mod message_bus {
use once_cell::sync::Lazy;
use tokio::sync::broadcast::{
channel,
error::{RecvError, TryRecvError},
Receiver, Sender,
};
pub struct Subscriber<T: Clone>(Receiver<T>);
impl<T> Subscriber<T>
where
T: Clone,
{
pub fn try_recv(&mut self) -> Option<T> {
loop {
match self.0.try_recv() {
Ok(v) => return Some(v),
Err(TryRecvError::Empty) => return None,
Err(TryRecvError::Lagged(_)) => {} Err(TryRecvError::Closed) => unreachable!(), }
}
}
pub async fn recv(&mut self) -> T {
loop {
match self.0.recv().await {
Ok(msg) => return msg,
Err(RecvError::Lagged(_)) => {} Err(RecvError::Closed) => unreachable!(), }
}
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
pub use sub_topic::SubTopic;
#[allow(missing_docs)]
pub mod sub_topic {
use super::*;
#[doc(hidden)]
#[allow(non_upper_case_globals)]
static TOPIC_SubTopic: Lazy<Sender<SubTopic>> = Lazy::new(|| channel(1).0);
#[doc(hidden)]
#[allow(non_upper_case_globals)]
static TOPIC_SubTopic_Foo: Lazy<Sender<u32>> = Lazy::new(|| channel(1).0);
#[doc(hidden)]
#[allow(non_upper_case_globals)]
static TOPIC_SubTopic_Bar: Lazy<Sender<u8>> = Lazy::new(|| channel(1).0);
#[derive(Clone)]
pub enum SubTopic {
Foo(u32),
Bar(u8),
}
impl SubTopic {
pub fn subscribe() -> Subscriber<SubTopic> {
Subscriber(TOPIC_SubTopic.subscribe())
}
}
pub fn publish(payload: SubTopic) {
TOPIC_SubTopic.send(payload).ok();
}
pub struct Foo {}
impl Foo {
pub fn subscribe() -> Subscriber<u32> {
Subscriber(TOPIC_SubTopic_Foo.subscribe())
}
pub fn publish(payload: u32) {
TOPIC_SubTopic_Foo.send(payload.clone()).ok();
publish(SubTopic::Foo(payload))
}
}
pub struct Bar {}
impl Bar {
pub fn subscribe() -> Subscriber<u8> {
Subscriber(TOPIC_SubTopic_Bar.subscribe())
}
pub fn publish(payload: u8) {
TOPIC_SubTopic_Bar.send(payload.clone()).ok();
publish(SubTopic::Bar(payload))
}
}
}
pub struct SystemHealth {}
#[doc(hidden)]
#[allow(non_upper_case_globals)]
static TOPIC_SystemHealth: Lazy<Sender<String>> = Lazy::new(|| channel(1).0);
impl SystemHealth {
pub fn subscribe() -> Subscriber<String> {
Subscriber(TOPIC_SystemHealth.subscribe())
}
pub fn publish(payload: String) {
TOPIC_SystemHealth.send(payload).ok();
}
}
pub struct SomeData {}
#[doc(hidden)]
#[allow(non_upper_case_globals)]
static TOPIC_SomeData: Lazy<Sender<u32>> = Lazy::new(|| channel(1).0);
impl SomeData {
pub fn subscribe() -> Subscriber<u32> {
Subscriber(TOPIC_SomeData.subscribe())
}
pub fn publish(payload: u32) {
TOPIC_SomeData.send(payload).ok();
}
}
}
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
pretty_env_logger::init();
tokio::spawn(async {
let mut sub1 = message_bus::SomeData::subscribe();
loop {
let msg = sub1.recv().await;
println!("Got {msg:?} on task 1");
}
});
tokio::spawn(async {
let mut sub1 = message_bus::SomeData::subscribe();
loop {
let msg = sub1.recv().await;
println!("Got {msg} on task 2");
sleep(Duration::from_millis(150)).await;
}
});
tokio::spawn(async {
let mut sub1 = message_bus::SomeData::subscribe();
loop {
let msg = sub1.recv().await;
println!("Got {msg:?} on task 3");
sleep(Duration::from_millis(1_000)).await;
}
});
tokio::spawn(async {
for i in 0..100 {
message_bus::SomeData::publish(i);
sleep(Duration::from_millis(50)).await;
}
})
.await
.ok();
println!("Hello, world!");
}