feat: lazy cache scrub

This commit is contained in:
ohaiibuzzle 2024-09-19 11:51:22 +07:00
parent 0fd52dc731
commit c6eddbbf95

View File

@ -9,23 +9,41 @@ import (
type DNSCacheEntry struct { type DNSCacheEntry struct {
ip string ip string
expiry_timer *time.Timer expiry time.Time
} }
type DNSCache struct { type DNSCache struct {
cacheMap map[string]DNSCacheEntry cacheMap map[string]DNSCacheEntry
cacheLock sync.RWMutex cacheLock sync.RWMutex
scrubbingTicker *time.Ticker
} }
var dnsCache *DNSCache var dnsCache *DNSCache
var once sync.Once var once sync.Once
func scrubDNSCache() {
for {
<-dnsCache.scrubbingTicker.C
dnsCache.cacheLock.Lock()
for k, v := range dnsCache.cacheMap {
if v.expiry.Before(time.Now()) {
delete(dnsCache.cacheMap, k)
}
}
dnsCache.cacheLock.Unlock()
}
}
func GetCache() *DNSCache { func GetCache() *DNSCache {
once.Do(func() { once.Do(func() {
dnsCache = &DNSCache{ dnsCache = &DNSCache{
cacheMap: make(map[string]DNSCacheEntry), cacheMap: make(map[string]DNSCacheEntry),
cacheLock: sync.RWMutex{}, cacheLock: sync.RWMutex{},
scrubbingTicker: time.NewTicker(time.Duration(1 * time.Hour)), // Hourly cache scrub
} }
go scrubDNSCache()
}) })
return dnsCache return dnsCache
} }
@ -40,21 +58,30 @@ func (d *DNSCache) Set(key string, value string) {
d.cacheMap[key] = DNSCacheEntry{ d.cacheMap[key] = DNSCacheEntry{
ip: value, ip: value,
expiry_timer: time.AfterFunc(time.Duration(*&util.GetConfig().DnsCacheTTL)*time.Second, func() { expiry: time.Now().Add(time.Duration(*&util.GetConfig().DnsCacheTTL) * time.Second),
d.cacheLock.Lock()
defer d.cacheLock.Unlock()
delete(d.cacheMap, key)
}),
} }
} }
func (d *DNSCache) Get(key string) (string, bool) { func (d *DNSCache) Get(key string) (string, bool) {
d.cacheLock.RLock() d.cacheLock.RLock() // Read lock
defer d.cacheLock.RUnlock()
if value, ok := d.cacheMap[key]; ok { if value, ok := d.cacheMap[key]; ok {
return value.ip, true if value.expiry.Before(time.Now()) {
} ip := value.ip
d.cacheLock.RUnlock() // Read unlock
return ip, true
} else {
d.cacheLock.RUnlock() // Read unlock
d.cacheLock.Lock() // Lock for writing
delete(d.cacheMap, key)
d.cacheLock.Unlock() // Unlock
return "", false return "", false
} }
}
d.cacheLock.RUnlock() // Read unlock
return "", false
}