package dnscache import ( "net" "time" "fmt" cache "github.com/pmylund/go-cache" "github.com/sirupsen/logrus" ) // DnsCacheItem represents single record in cache type DnsCacheItem struct { Addrs []string } // DnsCacheStorage is an in-memory cache of auto-purged dns query ip responses type DnsCacheStorage struct { cache *cache.Cache } func NewDnsCacheStorage(expiration, checkInterval time.Duration) *DnsCacheStorage { storage := DnsCacheStorage{cache.New(expiration, checkInterval)} return &storage } // Items returns map of non expired dns cache items func (dc *DnsCacheStorage) Items(includeExpired bool) map[string]DnsCacheItem { var allItems = dc.cache.Items() nonExpiredItems := map[string]DnsCacheItem{} for k, v := range allItems { if !includeExpired && v.Expired() { continue } nonExpiredItems[k] = v.Object.(DnsCacheItem) } return nonExpiredItems } // Get returns non expired item from cache func (dc *DnsCacheStorage) Get(key string) (DnsCacheItem, bool) { item, found := dc.cache.Get(key) if !found { return DnsCacheItem{}, false } return item.(DnsCacheItem), found } func (dc *DnsCacheStorage) Delete(key string) { dc.cache.Delete(key) } // FetchItem returns list of ips from cache or resolves them and add to cache func (dc *DnsCacheStorage) FetchItem(hostName string) ([]string, error) { if hostName == "" { return nil, fmt.Errorf("hostName can't be empty. hostName=%v", hostName) } item, ok := dc.Get(hostName) if ok { logger.WithFields(logrus.Fields{ "hostName": hostName, "addrs": item.Addrs, }).Debug("Dns record was populated from cache") return item.Addrs, nil } addrs, err := dc.resolveDNSRecord(hostName) if err != nil { return nil, err } dc.Set(hostName, addrs) return addrs, nil } func (dc *DnsCacheStorage) Set(key string, addrs []string) { logger.Debugf("Adding dns record to cache: key=%q, addrs=%q", key, addrs) dc.cache.Set(key, DnsCacheItem{addrs}, cache.DefaultExpiration) } // Clear deletes all records from cache func (dc *DnsCacheStorage) Clear() { dc.cache.Flush() } func (dc *DnsCacheStorage) resolveDNSRecord(host string) ([]string, error) { return net.LookupHost(host) }