use futures::StreamExt; use indicatif::ProgressBar; use instance_chart::{discovery, ChartBuilder}; use std::time::Duration; #[tokio::main] async fn main() { let jobs: Vec<_> = (1024..10_000u16) .into_iter() .map(port_can_multicast) .collect(); let mut ok = Vec::new(); let mut bad = Vec::new(); let pb = ProgressBar::new(jobs.len() as u64); let mut jobs = futures::stream::iter(jobs).buffer_unordered(400); while let Some(res) = jobs.next().await { pb.inc(1); match res { Ok(port) => { ok.push(port) } Err(port) => bad.push(port), } } pb.finish(); if ok.len() < bad.len() { println!("ports that can be used: {ok:?}"); } else { println!("ports that can not be used: {bad:?}"); } } async fn port_can_multicast(port: u16) -> Result { let a = node(1, 2, port); let b = node(2, 2, port); let timeout = tokio::time::sleep(Duration::from_millis(1000)); tokio::select! { res = a => res.map_err(|_| port).map(|()| port), res = b => res.map_err(|_| port).map(|()| port), _ = timeout => Err(port), } } async fn node(id: u64, cluster_size: u16, port: u16) -> Result<(), ()> { let chart = ChartBuilder::new() .with_id(id) .with_service_port(42) .with_discovery_port(port) .local_discovery(true) .finish() .map_err(|_| ())?; let maintain = discovery::maintain(chart.clone()); let discover = discovery::found_everyone(&chart, cluster_size); tokio::select! { _ = maintain => unreachable!(), _ = discover => Ok(()), } }