platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
119
selective-vpn-api/app/resolver/planning.go
Normal file
119
selective-vpn-api/app/resolver/planning.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package resolver
|
||||
|
||||
type ResolvePlanningInput struct {
|
||||
Domains []string
|
||||
Now int
|
||||
TTL int
|
||||
PrecheckDue bool
|
||||
PrecheckMaxDomains int
|
||||
StaleKeepSec int
|
||||
NegTTLNX int
|
||||
NegTTLTimeout int
|
||||
NegTTLTemporary int
|
||||
NegTTLOther int
|
||||
}
|
||||
|
||||
type ResolvePlanningResult struct {
|
||||
Fresh map[string][]string
|
||||
ToResolve []string
|
||||
CacheNegativeHits int
|
||||
QuarantineHits int
|
||||
StaleHits int
|
||||
PrecheckScheduled int
|
||||
}
|
||||
|
||||
func BuildResolvePlanning(
|
||||
in ResolvePlanningInput,
|
||||
domainCache *DomainCacheState,
|
||||
cacheSourceForHost func(string) DomainCacheSource,
|
||||
logf func(string, ...any),
|
||||
) ResolvePlanningResult {
|
||||
result := ResolvePlanningResult{
|
||||
Fresh: map[string][]string{},
|
||||
}
|
||||
if domainCache == nil {
|
||||
result.ToResolve = append(result.ToResolve, in.Domains...)
|
||||
return result
|
||||
}
|
||||
|
||||
resolveSource := cacheSourceForHost
|
||||
if resolveSource == nil {
|
||||
resolveSource = func(string) DomainCacheSource { return DomainCacheSourceDirect }
|
||||
}
|
||||
|
||||
for _, d := range in.Domains {
|
||||
source := resolveSource(d)
|
||||
if ips, ok := domainCache.Get(d, source, in.Now, in.TTL); ok {
|
||||
result.Fresh[d] = ips
|
||||
if logf != nil {
|
||||
logf("cache hit[%s]: %s -> %v", source, d, ips)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Quarantine has priority over negative TTL cache so 24h quarantine
|
||||
// is not silently overridden by shorter negative cache windows.
|
||||
if state, age, ok := domainCache.GetQuarantine(d, source, in.Now); ok {
|
||||
kind, hasKind := domainCache.GetLastErrorKind(d, source)
|
||||
timeoutKind := hasKind && kind == DNSErrorTimeout
|
||||
if in.PrecheckDue && result.PrecheckScheduled < in.PrecheckMaxDomains {
|
||||
// Timeout-based quarantine is rechecked in background batch and should
|
||||
// not flood trace with per-domain debug lines.
|
||||
if timeoutKind {
|
||||
result.QuarantineHits++
|
||||
if in.StaleKeepSec > 0 {
|
||||
if staleIPs, staleAge, ok := domainCache.GetStale(d, source, in.Now, in.StaleKeepSec); ok {
|
||||
result.StaleHits++
|
||||
result.Fresh[d] = staleIPs
|
||||
if logf != nil {
|
||||
logf("cache stale-keep (quarantine)[age=%ds]: %s -> %v", staleAge, d, staleIPs)
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
result.PrecheckScheduled++
|
||||
result.ToResolve = append(result.ToResolve, d)
|
||||
if logf != nil {
|
||||
logf("precheck schedule[quarantine/%s age=%ds]: %s (%s)", state, age, d, source)
|
||||
}
|
||||
continue
|
||||
}
|
||||
result.QuarantineHits++
|
||||
if logf != nil {
|
||||
logf("cache quarantine hit[%s age=%ds]: %s (%s)", state, age, d, source)
|
||||
}
|
||||
if in.StaleKeepSec > 0 {
|
||||
if staleIPs, staleAge, ok := domainCache.GetStale(d, source, in.Now, in.StaleKeepSec); ok {
|
||||
result.StaleHits++
|
||||
result.Fresh[d] = staleIPs
|
||||
if logf != nil {
|
||||
logf("cache stale-keep (quarantine)[age=%ds]: %s -> %v", staleAge, d, staleIPs)
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if kind, age, ok := domainCache.GetNegative(d, source, in.Now, in.NegTTLNX, in.NegTTLTimeout, in.NegTTLTemporary, in.NegTTLOther); ok {
|
||||
if in.PrecheckDue && result.PrecheckScheduled < in.PrecheckMaxDomains {
|
||||
if kind == DNSErrorTimeout {
|
||||
result.CacheNegativeHits++
|
||||
continue
|
||||
}
|
||||
result.PrecheckScheduled++
|
||||
result.ToResolve = append(result.ToResolve, d)
|
||||
if logf != nil {
|
||||
logf("precheck schedule[negative/%s age=%ds]: %s (%s)", kind, age, d, source)
|
||||
}
|
||||
continue
|
||||
}
|
||||
result.CacheNegativeHits++
|
||||
if logf != nil {
|
||||
logf("cache neg hit[%s/%s age=%ds]: %s", source, kind, age, d)
|
||||
}
|
||||
continue
|
||||
}
|
||||
result.ToResolve = append(result.ToResolve, d)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user