#![recursion_limit = "128"] fn main() { tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .unwrap() .block_on(async { tokio_main().await; }); } async fn tokio_main() { use hickory_resolver::{name_server::TokioConnectionProvider, TokioAsyncResolver}; let resolver = { // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration: #[cfg(any(unix, windows))] { // use the system resolver configuration TokioAsyncResolver::from_system_conf(TokioConnectionProvider::default()) } // For other operating systems, we can use one of the preconfigured definitions #[cfg(not(any(unix, windows)))] { // Directly reference the config types use hickory_resolver::config::{ResolverConfig, ResolverOpts}; // Get a new resolver with the google nameservers as the upstream recursive resolvers AsyncResolver::tokio( ResolverConfig::quad9(), ResolverOpts::default(), //runtime.handle().clone(), ) } } .map(std::sync::Arc::new) .expect("failed to create resolver"); // 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: &hickory_resolver::AsyncResolver

, ) -> 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: String = 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(|txt| { txt.iter() .map(|rdata| rdata.to_string()) .collect::>() }); println!(" {name} returned to {txts:?}"); } println!(); start_time.elapsed() } #[test] fn test_flush_cache() { main() }