use hickory_resolver::{Resolver, net::runtime::TokioRuntimeProvider, proto::rr::RData}; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); tokio_main().await; } async fn tokio_main() { // use the system resolver configuration let resolver = Resolver::builder_tokio() .expect("failed to create resolver") .build() .unwrap(); // Create some futures representing name lookups. let names = ["hickory-dns.org.", "estada.ch.", "wikipedia.org."]; let first_resolve = resolve_list(&names, &resolver).await; let cached_resolve = resolve_list(&names, &resolver).await; resolver.clear_cache(); let second_resolve = resolve_list(&names, &resolver).await; println!("first_resolve: {first_resolve:?}"); println!("cached_resolve: {cached_resolve:?}"); println!("second_resolve: {second_resolve:?}"); // Drop the resolver, which means that the runtime will become idle. drop(resolver); } async fn resolve_list( names: &[&str], resolver: &Resolver, ) -> tokio::time::Duration { use tokio::time::Instant; let start_time = Instant::now(); // Create the resolve requests first let futures = names .iter() .map(|name: &&str| { let name = name.to_string(); let resolver = resolver.clone(); let future = { let name = name.clone(); tokio::spawn(async move { resolver.txt_lookup(name).await }) }; (name, future) }) .collect::>(); // Go through the list of resolution operations in parallel and wait for them to complete. for (name, lookup) in futures { let txts = lookup .await .expect("unable to spawn resolver") .map(|lookup| { lookup .answers() .iter() .filter_map(|record| match &record.data { RData::TXT(txt) => Some(txt.to_string()), _ => None, }) .collect::>() }); println!(" {name} returned to {txts:?}"); } println!(); start_time.elapsed() } #[cfg(test)] mod tests { #[tokio::test] async fn test_flush_cache() { test_support::subscribe(); super::tokio_main().await; } }