dnscache

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2025 License: MIT Imports: 4 Imported by: 2

README

dnscache

import "github.com/cognusion/dnscache"

Overview

Package dnscache caches DNS lookups. The package itself requires no non-standard modules, however a separate testing suite is used.

Based on https://github.com/viki-org/dnscache with modern Go facilities, no intrinsic goro leak, more flexibility, and more.

Example :

If you are using an http.Transport, you can use this cache by specifying a Dial function.

// Create a resolver somewhere
resolver := New(5 * time.Minute)

transport := &http.Transport{
    MaxIdleConnsPerHost: 64,
    Dial: func(network string, address string) (net.Conn, error) {
        separator := strings.LastIndex(address, ":")
        ip, _ := resolver.FetchOneString(address[:separator])
        return net.Dial("tcp", ip+address[separator:])
    },
}

// e.g.
http.DefaultTransport = transport

Index

Examples
Package files

cache.go dnscache.go

Variables

var (
    // RefreshSleepTime is the delay between Refresh (and auto-refresh)
    // lookups, to keep the resolver threads from piling up.
    // Changes after a Resolver is instantiated are ignored.
    RefreshSleepTime = 1 * time.Second

    // RefreshShuffle is used to control whether the addresses are shuffled during Refresh,
    // to avoid long-tail misses on sufficiently large caches.
    // Changes after a Resolver is instantiated are ignored.
    RefreshShuffle = true
)

type Resolver

type Resolver struct {
    // contains filtered or unexported fields
}

Resolver is a goro-safe caching DNS resolver.

func New
func New(refreshRate time.Duration) *Resolver

New returns a properly instantiated Resolver. If the refreshRate is non-zero, a goro will refresh all of the entries after that Duration.

Example New:
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)
func NewFromConfig
func NewFromConfig(config *ResolverConfig) *Resolver

NewFromConfig returns a properly instantiated resolver, using the provided Cache and the provided AutoRefresh* values. NOTE: If using an LRU-style cache, setting the AutoRefreshInterval as large as feasible is advised, to keep the cache calculus correct.

Example NewFromConfig:

If you want to specify your cache style, then NewFromConfig is for you.

theCache, err := cache.NewLRU(
    cache.NewConfigOption(cache.ConfigSize, 100),                       // Keep up to 100 items in the cache
    cache.NewConfigOption(cache.ConfigRefreshType, cache.RefreshBatch), // Batch refreshes
    cache.NewConfigOption(cache.ConfigRefreshBatchSize, 10),            // Refresh in batches of 10
)
if err != nil {
    // don't actually do this.
        panic(err)
    }

    //refresh items every 5 minutes
    resolver := NewFromConfig(&ResolverConfig{
        Cache:               theCache,
        AutoRefreshInterval: 5 * time.Minute,
    })
    //get an array of net.IP
    ips, _ := resolver.Fetch("dns.google.com")
    fmt.Printf("%+v\n", ips)
func NewWithRefreshTimeout
func NewWithRefreshTimeout(refreshRate, refreshTimeout time.Duration) *Resolver

NewWithRefreshTimeout returns a properly instantiated Resolver. If the refreshRate is non-zero, a goro will refresh all of the entries after that Duration. If refreshTimeout is non-zero, each auto-refresh iteraction will timeout after the specified duration (expressed as a deadline).

Example NewWithRefreshTimeout:
//refresh items every 5 minutes, timeout each refresh after 1 minute.
resolver := NewWithRefreshTimeout(time.Minute*5, time.Minute*1)
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)
func (*Resolver) Close
func (r *Resolver) Close() error

Close signals the auto-refresh goro, if any, to quit. This is safe to call once, in any thread, regardless of whether or not auto-refresh is used.

func (*Resolver) Fetch
func (r *Resolver) Fetch(address string) ([]net.IP, error)

Fetch returns a collection of IPs from cache, or a live lookup if not.

Example Resolver_Fetch:
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)
func (*Resolver) FetchOne
func (r *Resolver) FetchOne(address string) (net.IP, error)

FetchOne returns a single IP from cache, or a live lookup if not.

Example Resolver_FetchOne:
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get the first net.IP
ip, _ := resolver.FetchOne("dns.google.com")
fmt.Printf("%+v\n", ip)
func (*Resolver) FetchOneString
func (r *Resolver) FetchOneString(address string) (string, error)

FetchOneString returns a single IP -as a string- from cache, or a live lookup if not.

Example Resolver_FetchOneString:
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get the first net.IP as string
ipString, _ := resolver.FetchOneString("dns.google.com")
fmt.Printf("%s\n", ipString)
func (*Resolver) Lookup
func (r *Resolver) Lookup(address string) ([]net.IP, error)

Lookup returns a collection of IPs from a live lookup, and updates the cache. Most callers should use one of the Fetch functions.

func (*Resolver) Purge
func (r *Resolver) Purge()

Purge will remove all entries. To comply with ResolverCache.

func (*Resolver) Refresh
func (r *Resolver) Refresh()

Refresh will iterate over cache items, and performing a live lookup one every RefreshSleepTime.

func (*Resolver) RefreshTimeout
func (r *Resolver) RefreshTimeout(timeout time.Duration)

RefreshTimeout will iterate over cache items, and performing a live lookup one every RefreshSleepTime, until completed or the stated timeout expires.

type ResolverCache

type ResolverCache interface {
    // Fetch retrieves a collection from the cache,
    // or performs a live lookup and adds it to the cache.
    Fetch(string) ([]net.IP, error)
    // Lookup performs a live lookup,
    // and adds the results to the cache.
    Lookup(address string) ([]net.IP, error)
    // Purge removes all entries from the cache.
    Purge()
    // Refresh will crawl the cache and update their entries.
    // A timeout of 0 must mean no timeout.
    // Refresh should honor RefreshSleepTime for per-lookup
    // intervals unless the cache mechanism exposes its own
    // tunables.
    // Refresh may honor RefreshShuffle if it is practical or desirable.
    Refresh(timeout time.Duration)
    // Close should be used to signal end of operations.
    // The cache should be considered unusable after this.
    // Close may return an error, but should not assume it is consumed.
    Close() error
    // Add will upsert a collection into the cache.
    Add(address string, ips []net.IP)
    // Remove will remove a collection from the cache, if it exists.
    Remove(address string)
    // Get will return a collection from the cache, also bool if
    // a collection was retrieved.
    Get(address string) ([]net.IP, bool)
    // Len will return the number of items in the cache.
    // Eventually-consistent or lazy caches may return estimates.
    Len() int
}

ResolverCache is an interface to define different caches for Resolver. All functions defined here must be goro-safe.

type ResolverConfig

type ResolverConfig struct {
    Cache               ResolverCache
    AutoRefreshInterval time.Duration
    AutoRefreshTimeout  time.Duration
}

ResolverConfig is a common configuration structure for the Resolver.


Generated by godoc2md

Documentation

Overview

Package dnscache caches DNS lookups. The package itself requires no non-standard modules, however a separate testing suite is used.

Based on https://github.com/viki-org/dnscache with modern Go facilities, no intrinsic goro leak, more flexibility, and more.

Example

If you are using an `http.Transport`, you can use this cache by specifying a `Dial` function.

// Create a resolver somewhere
resolver := New(5 * time.Minute)

transport := &http.Transport{
	MaxIdleConnsPerHost: 64,
	Dial: func(network string, address string) (net.Conn, error) {
		separator := strings.LastIndex(address, ":")
		ip, _ := resolver.FetchOneString(address[:separator])
		return net.Dial("tcp", ip+address[separator:])
	},
}

// e.g.
http.DefaultTransport = transport

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// RefreshSleepTime is the delay between Refresh (and auto-refresh)
	// lookups, to keep the resolver threads from piling up.
	// Changes after a Resolver is instantiated are ignored.
	RefreshSleepTime = 1 * time.Second

	// RefreshShuffle is used to control whether the addresses are shuffled during Refresh,
	// to avoid long-tail misses on sufficiently large caches.
	// Changes after a Resolver is instantiated are ignored.
	RefreshShuffle = true
)

Functions

This section is empty.

Types

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver is a goro-safe caching DNS resolver.

func New

func New(refreshRate time.Duration) *Resolver

New returns a properly instantiated Resolver. If the refreshRate is non-zero, a goro will refresh all of the entries after that Duration.

Example
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)

func NewFromConfig added in v1.0.0

func NewFromConfig(config *ResolverConfig) *Resolver

NewFromConfig returns a properly instantiated resolver, using the provided Cache and the provided AutoRefresh* values. NOTE: If using an LRU-style cache, setting the AutoRefreshInterval as large as feasible is advised, to keep the cache calculus correct.

Example

If you want to specify your cache style, then NewFromConfig is for you.

theCache, err := cache.NewLRU(
	cache.NewConfigOption(cache.ConfigSize, 100),                       // Keep up to 100 items in the cache
	cache.NewConfigOption(cache.ConfigRefreshType, cache.RefreshBatch), // Batch refreshes
	cache.NewConfigOption(cache.ConfigRefreshBatchSize, 10),            // Refresh in batches of 10
)
if err != nil {
	// don't actually do this.
	panic(err)
}

//refresh items every 5 minutes
resolver := NewFromConfig(&ResolverConfig{
	Cache:               theCache,
	AutoRefreshInterval: 5 * time.Minute,
})
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)

func NewWithRefreshTimeout added in v0.6.0

func NewWithRefreshTimeout(refreshRate, refreshTimeout time.Duration) *Resolver

NewWithRefreshTimeout returns a properly instantiated Resolver. If the refreshRate is non-zero, a goro will refresh all of the entries after that Duration. If refreshTimeout is non-zero, each auto-refresh iteraction will timeout after the specified duration (expressed as a deadline).

Example
//refresh items every 5 minutes, timeout each refresh after 1 minute.
resolver := NewWithRefreshTimeout(time.Minute*5, time.Minute*1)
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)

func (*Resolver) Close

func (r *Resolver) Close() error

Close signals the auto-refresh goro, if any, to quit. This is safe to call once, in any thread, regardless of whether or not auto-refresh is used.

func (*Resolver) Fetch

func (r *Resolver) Fetch(address string) ([]net.IP, error)

Fetch returns a collection of IPs from cache, or a live lookup if not.

Example
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get an array of net.IP
ips, _ := resolver.Fetch("dns.google.com")
fmt.Printf("%+v\n", ips)

func (*Resolver) FetchOne

func (r *Resolver) FetchOne(address string) (net.IP, error)

FetchOne returns a single IP from cache, or a live lookup if not.

Example
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get the first net.IP
ip, _ := resolver.FetchOne("dns.google.com")
fmt.Printf("%+v\n", ip)

func (*Resolver) FetchOneString

func (r *Resolver) FetchOneString(address string) (string, error)

FetchOneString returns a single IP -as a string- from cache, or a live lookup if not.

Example
//refresh items every 5 minutes
resolver := New(time.Minute * 5)
//get the first net.IP as string
ipString, _ := resolver.FetchOneString("dns.google.com")
fmt.Printf("%s\n", ipString)

func (*Resolver) Lookup

func (r *Resolver) Lookup(address string) ([]net.IP, error)

Lookup returns a collection of IPs from a live lookup, and updates the cache. Most callers should use one of the Fetch functions.

func (*Resolver) Purge added in v1.0.0

func (r *Resolver) Purge()

Purge will remove all entries. To comply with ResolverCache.

func (*Resolver) Refresh

func (r *Resolver) Refresh()

Refresh will iterate over cache items, and performing a live lookup one every RefreshSleepTime.

func (*Resolver) RefreshTimeout added in v0.6.0

func (r *Resolver) RefreshTimeout(timeout time.Duration)

RefreshTimeout will iterate over cache items, and performing a live lookup one every RefreshSleepTime, until completed or the stated timeout expires.

type ResolverCache added in v1.0.0

type ResolverCache interface {
	// Fetch retrieves a collection from the cache,
	// or performs a live lookup and adds it to the cache.
	Fetch(string) ([]net.IP, error)
	// Lookup performs a live lookup,
	// and adds the results to the cache.
	Lookup(address string) ([]net.IP, error)
	// Purge removes all entries from the cache.
	Purge()
	// Refresh will crawl the cache and update their entries.
	// A timeout of 0 must mean no timeout.
	// Refresh should honor RefreshSleepTime for per-lookup
	// intervals unless the cache mechanism exposes its own
	// tunables.
	// Refresh may honor RefreshShuffle if it is practical or desirable.
	Refresh(timeout time.Duration)
	// Close should be used to signal end of operations.
	// The cache should be considered unusable after this.
	// Close may return an error, but should not assume it is consumed.
	Close() error
	// Add will upsert a collection into the cache.
	Add(address string, ips []net.IP)
	// Remove will remove a collection from the cache, if it exists.
	Remove(address string)
	// Get will return a collection from the cache, also bool if
	// a collection was retrieved.
	Get(address string) ([]net.IP, bool)
	// Len will return the number of items in the cache.
	// Eventually-consistent or lazy caches may return estimates.
	Len() int
}

ResolverCache is an interface to define different caches for Resolver. All functions defined here must be goro-safe.

type ResolverConfig added in v1.0.0

type ResolverConfig struct {
	Cache               ResolverCache
	AutoRefreshInterval time.Duration
	AutoRefreshTimeout  time.Duration
}

ResolverConfig is a common configuration structure for the Resolver.

Directories

Path Synopsis
Package cache provides caching options to DNSCache, or other similar consumers.
Package cache provides caching options to DNSCache, or other similar consumers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL