holdon 0.2.1

Wait for anything. Know why if it doesn't.
Documentation
use std::net::ToSocketAddrs;
use std::time::Instant;

use tokio::time::timeout;

use super::hint::hints;
use super::{AttemptCtx, err_stage, ok_stage};
use crate::diagnostic::{Stage, StageKind};
use crate::util::format_error_chain;

pub(super) async fn probe(host: &str, ctx: AttemptCtx) -> Vec<Stage> {
    let start = Instant::now();
    let host_owned = host.to_owned();
    let task = tokio::task::spawn_blocking(move || {
        (host_owned.as_str(), 0u16)
            .to_socket_addrs()
            .map(Iterator::count)
    });
    let stage = match timeout(ctx.attempt_timeout, task).await {
        Ok(Ok(Ok(n))) if n > 0 => ok_stage(StageKind::Dns, start.elapsed()),
        Ok(Ok(Ok(_))) => err_stage(StageKind::Dns, start.elapsed(), "no addresses", None),
        Ok(Ok(Err(e))) => err_stage(
            StageKind::Dns,
            start.elapsed(),
            format_error_chain(&e),
            Some(hints::DNS_HINT),
        ),
        Ok(Err(e)) => err_stage(
            StageKind::Dns,
            start.elapsed(),
            format!("resolver task: {e}"),
            None,
        ),
        Err(_) => err_stage(StageKind::Dns, ctx.attempt_timeout, hints::TIMED_OUT, None),
    };
    vec![stage]
}