platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
115
selective-vpn-api/app/resolver/resolve_batch.go
Normal file
115
selective-vpn-api/app/resolver/resolve_batch.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package resolver
|
||||
|
||||
type ResolveBatchInput struct {
|
||||
ToResolve []string
|
||||
Workers int
|
||||
Now int
|
||||
StaleKeepSec int
|
||||
}
|
||||
|
||||
type ResolveBatchResult struct {
|
||||
DNSStats DNSMetrics
|
||||
ResolvedNowDNS int
|
||||
ResolvedNowStale int
|
||||
UnresolvedAfterAttempts int
|
||||
StaleHitsDelta int
|
||||
}
|
||||
|
||||
func ExecuteResolveBatch(
|
||||
in ResolveBatchInput,
|
||||
resolved map[string][]string,
|
||||
domainCache *DomainCacheState,
|
||||
cacheSourceForHost func(string) DomainCacheSource,
|
||||
resolveHost func(string) ([]string, DNSMetrics),
|
||||
logf func(string, ...any),
|
||||
) ResolveBatchResult {
|
||||
out := ResolveBatchResult{}
|
||||
if len(in.ToResolve) == 0 || resolveHost == nil || domainCache == nil {
|
||||
return out
|
||||
}
|
||||
|
||||
workers := in.Workers
|
||||
if workers < 1 {
|
||||
workers = 1
|
||||
}
|
||||
if workers > 500 {
|
||||
workers = 500
|
||||
}
|
||||
resolveSource := cacheSourceForHost
|
||||
if resolveSource == nil {
|
||||
resolveSource = func(string) DomainCacheSource { return DomainCacheSourceDirect }
|
||||
}
|
||||
|
||||
type result struct {
|
||||
host string
|
||||
ips []string
|
||||
stats DNSMetrics
|
||||
}
|
||||
|
||||
jobs := make(chan string, len(in.ToResolve))
|
||||
results := make(chan result, len(in.ToResolve))
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
go func() {
|
||||
for host := range jobs {
|
||||
ips, stats := resolveHost(host)
|
||||
results <- result{host: host, ips: ips, stats: stats}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for _, host := range in.ToResolve {
|
||||
jobs <- host
|
||||
}
|
||||
close(jobs)
|
||||
|
||||
for i := 0; i < len(in.ToResolve); i++ {
|
||||
r := <-results
|
||||
out.DNSStats.Merge(r.stats)
|
||||
hostErrors := r.stats.TotalErrors()
|
||||
if hostErrors > 0 && logf != nil {
|
||||
logf("resolve errors for %s: total=%d nxdomain=%d timeout=%d temporary=%d other=%d", r.host, hostErrors, r.stats.NXDomain, r.stats.Timeout, r.stats.Temporary, r.stats.Other)
|
||||
}
|
||||
if len(r.ips) > 0 {
|
||||
if resolved != nil {
|
||||
resolved[r.host] = r.ips
|
||||
}
|
||||
out.ResolvedNowDNS++
|
||||
source := resolveSource(r.host)
|
||||
domainCache.Set(r.host, source, r.ips, in.Now)
|
||||
if logf != nil {
|
||||
logf("%s -> %v", r.host, r.ips)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
staleApplied := false
|
||||
if hostErrors > 0 {
|
||||
source := resolveSource(r.host)
|
||||
domainCache.SetErrorWithStats(r.host, source, r.stats, in.Now)
|
||||
if in.StaleKeepSec > 0 && ShouldUseStaleOnError(r.stats) {
|
||||
if staleIPs, staleAge, ok := domainCache.GetStale(r.host, source, in.Now, in.StaleKeepSec); ok {
|
||||
out.StaleHitsDelta++
|
||||
out.ResolvedNowStale++
|
||||
staleApplied = true
|
||||
if resolved != nil {
|
||||
resolved[r.host] = staleIPs
|
||||
}
|
||||
if logf != nil {
|
||||
logf("cache stale-keep (error)[age=%ds]: %s -> %v", staleAge, r.host, staleIPs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !staleApplied {
|
||||
out.UnresolvedAfterAttempts++
|
||||
}
|
||||
if logf != nil && resolved != nil {
|
||||
if _, ok := resolved[r.host]; !ok {
|
||||
logf("%s: no IPs", r.host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user