Skip to main content

DnsCache

Struct DnsCache 

Source
pub struct DnsCache { /* private fields */ }
Expand description

A DNS resolution cache with TTL support and negative caching.

This cache stores resolved DNS entries and avoids repeated lookups for the same hostname within the TTL window. It also implements negative caching for failed lookups to prevent retry storms.

§Thread Safety

For use in async contexts, wrap with tokio::sync::Mutex. Instances should be created during engine initialization and passed down via dependency injection rather than using global singletons.

Implementations§

Source§

impl DnsCache

Source

pub fn new() -> Self

Create a new DNS cache with default settings.

Default values:

  • TTL: 300 seconds (5 minutes)
  • Negative TTL: 60 seconds (1 minute)
  • IPv4 preference: enabled
Source

pub fn with_ttl(default_ttl_secs: u64, negative_ttl_secs: u64) -> Self

Create a new DNS cache with custom TTL values.

§Arguments
  • default_ttl_secs - Time-to-live for successful resolutions (in seconds)
  • negative_ttl_secs - Time-to-live for failed lookups (in seconds)
Source

pub fn with_resolver(self, resolver: TokioAsyncResolver) -> Self

Inject a custom hickory resolver (useful for testing with a configured/mock resolver).

This replaces the default resolver built during construction. The TTL settings and IPv4 preference are preserved.

Source

pub async fn resolve( &mut self, hostname: &str, port: u16, ) -> Result<Vec<SocketAddr>, String>

Resolve a hostname to socket addresses, using cache if valid.

Resolution strategy:

  1. Check positive cache — return immediately if entry exists and is not expired
  2. Check negative cache — return error if lookup recently failed
  3. Try the fully-async hickory resolver (no blocking getaddrinfo); on success the record TTL is capped at default_ttl and the result is cached
  4. If hickory is unavailable or errors, fall back to tokio::net::lookup_host (blocking getaddrinfo on a tokio thread pool) so behavior stays robust
  5. On success: sort addresses by IPv4 preference, cache result, return
  6. On failure: record in negative cache, return error
§Arguments
  • hostname - The hostname to resolve (e.g., “example.com”)
  • port - The port number to include in resolved addresses
§Returns

A vector of resolved SocketAddr on success, or an error string on failure.

Source

pub async fn force_refresh( &mut self, hostname: &str, port: u16, ) -> Result<Vec<SocketAddr>, String>

Force refresh a specific hostname, bypassing any cached entry.

This removes any existing cache entry for the hostname and performs a fresh DNS resolution. Useful when you know the DNS records may have changed.

§Arguments
  • hostname - The hostname to re-resolve
  • port - The port number for resolved addresses
Source

pub fn clear(&mut self)

Clear all cached entries (both positive and negative).

Source

pub fn purge_expired(&mut self) -> usize

Remove expired entries from the cache.

Call this periodically (e.g., every few minutes) to reclaim memory from stale entries. Also cleans up expired negative cache entries.

§Returns

The number of entries that were removed.

Source

pub fn set_ipv4_preference(&mut self, prefer_ipv4: bool)

Set whether IPv4 addresses should be preferred over IPv6.

When enabled, resolved addresses are sorted with IPv4 addresses first. This matches the behavior of C++ aria2 which prefers IPv4 by default.

Source

pub fn len(&self) -> usize

Get the number of currently cached (non-expired) entries.

Source

pub fn is_empty(&self) -> bool

Check if the cache contains no entries.

Source

pub fn default_ttl(&self) -> Duration

Get the default TTL setting.

Source

pub fn negative_ttl(&self) -> Duration

Get the negative TTL setting.

Source

pub fn record_failure(&mut self, hostname: &str)

Manually record a failed lookup in the negative cache.

This is useful for testing negative cache behavior without depending on network DNS resolution.

Source

pub fn resolve_no_network( &mut self, hostname: &str, port: u16, ) -> Result<Vec<SocketAddr>, String>

Check cache only (no network resolution).

Returns cached addresses if available, or an error if the entry is in the negative cache or not cached at all. This is useful for testing cache behavior without network dependencies.

Trait Implementations§

Source§

impl Default for DnsCache

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more