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() {
let resolver = Resolver::builder_tokio()
.expect("failed to create resolver")
.build()
.unwrap();
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(resolver);
}
async fn resolve_list(
names: &[&str],
resolver: &Resolver<TokioRuntimeProvider>,
) -> tokio::time::Duration {
use tokio::time::Instant;
let start_time = Instant::now();
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::<Vec<_>>();
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::<Vec<_>>()
});
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;
}
}