Add dns cache clearing mechanisms
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/safing/portbase/database"
|
||||
"github.com/safing/portbase/database/query"
|
||||
"github.com/safing/portbase/database/record"
|
||||
"github.com/safing/portbase/log"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -14,6 +17,8 @@ var (
|
||||
AlwaysSetRelativateExpiry: 2592000, // 30 days
|
||||
CacheSize: 256,
|
||||
})
|
||||
|
||||
nameRecordsKeyPrefix = "cache:intel/nameRecord/"
|
||||
)
|
||||
|
||||
// NameRecord is helper struct to RRCache to better save data to the database.
|
||||
@@ -33,11 +38,11 @@ type NameRecord struct {
|
||||
}
|
||||
|
||||
func makeNameRecordKey(domain string, question string) string {
|
||||
return fmt.Sprintf("cache:intel/nameRecord/%s%s", domain, question)
|
||||
return nameRecordsKeyPrefix + domain + question
|
||||
}
|
||||
|
||||
// GetNameRecord gets a NameRecord from the database.
|
||||
func GetNameRecord(domain string, question string) (*NameRecord, error) {
|
||||
func GetNameRecord(domain, question string) (*NameRecord, error) {
|
||||
key := makeNameRecordKey(domain, question)
|
||||
|
||||
r, err := recordDatabase.Get(key)
|
||||
@@ -64,6 +69,12 @@ func GetNameRecord(domain string, question string) (*NameRecord, error) {
|
||||
return new, nil
|
||||
}
|
||||
|
||||
// DeleteNameRecord deletes a NameRecord from the database.
|
||||
func DeleteNameRecord(domain, question string) error {
|
||||
key := makeNameRecordKey(domain, question)
|
||||
return recordDatabase.Delete(key)
|
||||
}
|
||||
|
||||
// Save saves the NameRecord to the database.
|
||||
func (rec *NameRecord) Save() error {
|
||||
if rec.Domain == "" || rec.Question == "" {
|
||||
@@ -73,3 +84,49 @@ func (rec *NameRecord) Save() error {
|
||||
rec.SetKey(makeNameRecordKey(rec.Domain, rec.Question))
|
||||
return recordDatabase.PutNew(rec)
|
||||
}
|
||||
|
||||
func clearNameCache(_ context.Context, _ interface{}) error {
|
||||
log.Debugf("resolver: name cache clearing started...")
|
||||
for {
|
||||
done, err := removeNameEntries(10000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if done {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeNameEntries(batchSize int) (bool, error) {
|
||||
iter, err := recordDatabase.Query(query.New(nameRecordsKeyPrefix))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
keys := make([]string, 0, batchSize)
|
||||
|
||||
var cnt int
|
||||
for r := range iter.Next {
|
||||
cnt++
|
||||
keys = append(keys, r.Key())
|
||||
|
||||
if cnt == batchSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
iter.Cancel()
|
||||
|
||||
for _, key := range keys {
|
||||
if err := recordDatabase.Delete(key); err != nil {
|
||||
log.Warningf("resolver: failed to remove name cache entry %q: %s", key, err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("resolver: successfully removed %d name cache entries", cnt)
|
||||
|
||||
// if we removed less entries that the batch size we
|
||||
// are done and no more entries exist
|
||||
return cnt < batchSize, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user