Use sync.Map

This commit is contained in:
风扇滑翔翼 2025-02-15 15:19:18 +00:00 committed by GitHub
parent 8322c1919c
commit 10a7c9b8b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -57,19 +57,17 @@ type record struct {
} }
var ( var (
dnsCache = make(map[string]record) dnsCache sync.Map
// global Lock? I'm not sure if I need finer grained locks. // global Lock? I'm not sure if this needs finer grained locks.
// If we do this, we will need to nest another layer of struct // If we do this, we will need to nest another layer of struct
dnsCacheLock sync.RWMutex updating sync.Mutex
updating sync.Mutex
) )
// QueryRecord returns the ECH config for given domain. // QueryRecord returns the ECH config for given domain.
// If the record is not in cache or expired, it will query the DOH server and update the cache. // If the record is not in cache or expired, it will query the DOH server and update the cache.
func QueryRecord(domain string, server string) ([]byte, error) { func QueryRecord(domain string, server string) ([]byte, error) {
dnsCacheLock.RLock() val, found := dnsCache.Load(domain)
rec, found := dnsCache[domain] rec, _ := val.(record)
dnsCacheLock.RUnlock()
if found && rec.expire.After(time.Now()) { if found && rec.expire.After(time.Now()) {
errors.LogDebug(context.Background(), "Cache hit for domain: ", domain) errors.LogDebug(context.Background(), "Cache hit for domain: ", domain)
return rec.echConfig, nil return rec.echConfig, nil
@ -79,9 +77,8 @@ func QueryRecord(domain string, server string) ([]byte, error) {
defer updating.Unlock() defer updating.Unlock()
// Try to get cache again after lock, in case another goroutine has updated it // Try to get cache again after lock, in case another goroutine has updated it
// This might happen when the core tring is just stared and multiple goroutines are trying to query the same domain // This might happen when the core tring is just stared and multiple goroutines are trying to query the same domain
dnsCacheLock.RLock() val, found = dnsCache.Load(domain)
rec, found = dnsCache[domain] rec, _ = val.(record)
dnsCacheLock.RUnlock()
if found && rec.expire.After(time.Now()) { if found && rec.expire.After(time.Now()) {
errors.LogDebug(context.Background(), "ECH Config cache hit for domain: ", domain, " after trying to get update lock") errors.LogDebug(context.Background(), "ECH Config cache hit for domain: ", domain, " after trying to get update lock")
return rec.echConfig, nil return rec.echConfig, nil
@ -99,14 +96,12 @@ func QueryRecord(domain string, server string) ([]byte, error) {
ttl = 600 ttl = 600
} }
// Get write lock and update cache // Update cache
dnsCacheLock.Lock()
defer dnsCacheLock.Unlock()
newRecored := record{ newRecored := record{
echConfig: echConfig, echConfig: echConfig,
expire: time.Now().Add(time.Second * time.Duration(ttl)), expire: time.Now().Add(time.Second * time.Duration(ttl)),
} }
dnsCache[domain] = newRecored dnsCache.Store(domain, newRecored)
return echConfig, nil return echConfig, nil
} }