use std::net::SocketAddr;
use std::time::Duration;
use weida::{Identity, Publisher, Runtime, RuntimeConfig, Subscriber, Trust};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let identity = Identity::generate()?;
let fingerprint = identity.fingerprint()?;
let server = Runtime::new(RuntimeConfig::default())?;
let listener = server.listener();
let binding = listener
.bind_quic("127.0.0.1:0".parse::<SocketAddr>()?, identity)
.await?;
let url = format!(
"weida://{fingerprint}@127.0.0.1:{}/md",
binding.local_addr().port()
);
let publisher = listener.publisher("/md")?;
println!("publishing on {url}");
println!(
" before anyone subscribed: publish reached {} subscribers",
publisher.publish("px.eur", &b"ignored"[..])?
);
let prices_rt = Runtime::new(RuntimeConfig::default())?;
let everything_rt = Runtime::new(RuntimeConfig::default())?;
let prices = prices_rt.subscriber(Trust::by_address());
prices.connect(&url).await?;
prices.subscribe("px.").await?;
let everything = everything_rt.subscriber(Trust::by_address());
everything.connect(&url).await?;
everything.subscribe("").await?;
await_filters(&publisher, 2).await;
println!(
" {} subscribers, {} filters\n",
publisher.subscriber_count(),
publisher.filter_count()
);
for (topic, payload) in [
("px.eur", "1.0847"),
("fx.usd", "0.9219"),
("px.gbp", "0.8461"),
] {
let reached = publisher.publish(topic, payload.as_bytes())?;
println!("published {topic:<8} {payload:<8} -> {reached} subscriber(s)");
}
println!();
show(&prices, "prices (filter \"px.\")", 2).await?;
show(&everything, "everything (filter \"\") ", 3).await?;
drop(prices);
drop(everything);
prices_rt.shutdown().await;
everything_rt.shutdown().await;
server.shutdown().await;
Ok(())
}
async fn show(sub: &Subscriber, label: &str, count: usize) -> Result<(), weida::Error> {
print!("{label} received:");
for _ in 0..count {
let transfer = sub.recv().await?;
let topic = transfer.meta().topic.clone().unwrap_or_default();
let body = transfer.collect(64 * 1024).await?;
print!(" {topic}={}", String::from_utf8_lossy(&body));
}
println!();
Ok(())
}
async fn await_filters(publisher: &Publisher, count: usize) {
for _ in 0..5_000 {
if publisher.filter_count() == count {
return;
}
tokio::time::sleep(Duration::from_millis(1)).await;
}
panic!("subscriptions never registered");
}