instance-chart 0.4.0

Chart (discover) instances of your application on the same network and or machine
Documentation
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<u16, u16> {
    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(()),
    }
}