Files
elmprodvpn/selective-vpn-api/app/resolver_pipeline.go

185 lines
5.5 KiB
Go

package app
import "time"
type resolverJobContext struct {
domains []string
metaSpecial []string
staticLines []string
wildcards wildcardMatcher
cfg dnsConfig
domainCache domainCacheState
ptrCache map[string]any
now int
precheckStatePath string
precheckEnvForced bool
precheckFileForced bool
tuning resolverRuntimeTuning
cacheSourceForHost func(string) domainCacheSource
cooldown *dnsRunCooldown
timeoutRecheck resolverTimeoutRecheckStats
}
func runResolverPipeline(ctx *resolverJobContext, res *resolverResult, logf func(string, ...any)) {
if ctx == nil || res == nil {
return
}
start := time.Now()
planning := buildResolverPlanning(
ctx.domains,
ctx.now,
ctx.tuning.TTL,
ctx.tuning.PrecheckDue,
ctx.tuning.PrecheckMaxDomains,
ctx.tuning.StaleKeepSec,
ctx.tuning.NegTTLNX,
ctx.tuning.NegTTLTimeout,
ctx.tuning.NegTTLTemporary,
ctx.tuning.NegTTLOther,
&ctx.domainCache,
ctx.cacheSourceForHost,
logf,
)
fresh := planning.Fresh
cacheNegativeHits := planning.CacheNegativeHits
quarantineHits := planning.QuarantineHits
staleHits := planning.StaleHits
precheckScheduled := planning.PrecheckScheduled
toResolve := planning.ToResolve
resolved := map[string][]string{}
for k, v := range fresh {
resolved[k] = v
}
toResolveTotal := len(toResolve)
liveP1 := 0
liveP2 := 0
liveP3 := 0
liveNXHeavyTotal := 0
liveNXHeavySkip := 0
toResolve, liveP1, liveP2, liveP3, liveNXHeavyTotal, liveNXHeavySkip = pickAdaptiveLiveBatch(
toResolve,
ctx.tuning.LiveBatchTarget,
ctx.now,
ctx.tuning.LiveBatchNXHeavyPct,
ctx.domainCache,
ctx.cacheSourceForHost,
ctx.wildcards,
)
liveDeferred := toResolveTotal - len(toResolve)
if liveDeferred < 0 {
liveDeferred = 0
}
if logf != nil {
logf("resolve: domains=%d cache_hits=%d cache_neg_hits=%d quarantine_hits=%d stale_hits=%d precheck_due=%t precheck_scheduled=%d to_resolve=%d to_resolve_total=%d deferred_by_live_batch=%d live_p1=%d live_p2=%d live_p3=%d live_nxheavy_total=%d live_nxheavy_skip=%d", len(ctx.domains), len(fresh), cacheNegativeHits, quarantineHits, staleHits, ctx.tuning.PrecheckDue, precheckScheduled, len(toResolve), toResolveTotal, liveDeferred, liveP1, liveP2, liveP3, liveNXHeavyTotal, liveNXHeavySkip)
}
resolveBatch := executeResolverBatch(
toResolve,
ctx.tuning.Workers,
ctx.now,
ctx.tuning.StaleKeepSec,
resolved,
&ctx.domainCache,
ctx.cacheSourceForHost,
func(host string) ([]string, dnsMetrics) {
return resolveHostGo(host, ctx.cfg, ctx.metaSpecial, ctx.wildcards, ctx.tuning.DNSTimeout, ctx.cooldown, logf)
},
logf,
)
dnsStats := resolveBatch.DNSStats
resolvedNowDNS := resolveBatch.ResolvedNowDNS
resolvedNowStale := resolveBatch.ResolvedNowStale
unresolvedAfterAttempts := resolveBatch.UnresolvedAfterAttempts
staleHits += resolveBatch.StaleHitsDelta
staticEntries, staticSkipped := parseStaticEntriesGo(ctx.staticLines, logf)
staticLabels, ptrLookups, ptrErrors := resolveStaticLabels(staticEntries, ctx.cfg, ctx.ptrCache, ctx.tuning.TTL, logf)
isWildcardHost := func(host string) bool {
switch ctx.cfg.Mode {
case DNSModeSmartDNS:
return true
case DNSModeHybridWildcard:
return ctx.wildcards.Match(host)
default:
return false
}
}
artifacts := buildResolverArtifacts(resolved, staticLabels, isWildcardHost)
res.IPMap = artifacts.IPMap
res.DirectIPMap = artifacts.DirectIPMap
res.WildcardIPMap = artifacts.WildcardIPMap
res.IPs = artifacts.IPs
res.DirectIPs = artifacts.DirectIPs
res.WildcardIPs = artifacts.WildcardIPs
res.DomainCache = ctx.domainCache.toMap()
res.PtrCache = ctx.ptrCache
logResolverSummary(
resolverSummaryLogInput{
DomainsTotal: len(ctx.domains),
FreshCount: len(fresh),
CacheNegativeHits: cacheNegativeHits,
QuarantineHits: quarantineHits,
StaleHits: staleHits,
ResolvedTotal: len(resolved),
UnresolvedAfterAttempts: unresolvedAfterAttempts,
LiveBatchTarget: ctx.tuning.LiveBatchTarget,
LiveDeferred: liveDeferred,
LiveP1: liveP1,
LiveP2: liveP2,
LiveP3: liveP3,
LiveBatchNXHeavyPct: ctx.tuning.LiveBatchNXHeavyPct,
LiveNXHeavyTotal: liveNXHeavyTotal,
LiveNXHeavySkip: liveNXHeavySkip,
StaticEntries: len(staticEntries),
StaticSkipped: staticSkipped,
UniqueIPs: len(res.IPs),
DirectIPs: len(res.DirectIPs),
WildcardIPs: len(res.WildcardIPs),
PtrLookups: ptrLookups,
PtrErrors: ptrErrors,
DNSStats: dnsStats,
TimeoutRecheck: ctx.timeoutRecheck,
DurationMS: time.Since(start).Milliseconds(),
DomainStateSummary: ctx.domainCache.formatStateSummary(ctx.now),
ResolvedNowDNS: resolvedNowDNS,
ResolvedNowStale: resolvedNowStale,
PrecheckDue: ctx.tuning.PrecheckDue,
PrecheckScheduled: precheckScheduled,
PrecheckStatePath: ctx.precheckStatePath,
},
logf,
)
_ = finalizeResolverPrecheck(
ctx.tuning.PrecheckDue,
ctx.precheckStatePath,
ctx.now,
ctx.timeoutRecheck,
ctx.tuning.LiveBatchTarget,
ctx.tuning.LiveBatchMin,
ctx.tuning.LiveBatchMax,
ctx.tuning.LiveBatchNXHeavyPct,
ctx.tuning.LiveBatchNXHeavyMin,
ctx.tuning.LiveBatchNXHeavyMax,
dnsStats,
liveDeferred,
resolvedNowDNS,
liveP1,
liveP2,
liveP3,
liveNXHeavyTotal,
liveNXHeavySkip,
toResolveTotal,
ctx.precheckFileForced,
precheckForcePath,
logf,
)
}