Files
elmprodvpn/selective-vpn-api/app/resolver/runtime_tuning.go

206 lines
5.6 KiB
Go

package resolver
import "time"
type ResolverRuntimeTuningInput struct {
TTL int
Workers int
Now int
PrecheckStatePath string
PrecheckEnvForced bool
PrecheckFileForced bool
}
type ResolverRuntimeTuning struct {
TTL int
Workers int
DNSTimeoutMS int
DNSTimeout time.Duration
PrecheckEverySec int
PrecheckMaxDomains int
TimeoutRecheckMax int
LiveBatchMin int
LiveBatchMax int
LiveBatchTarget int
LiveBatchNXHeavyMin int
LiveBatchNXHeavyMax int
LiveBatchNXHeavyPct int
PrecheckDue bool
StaleKeepSec int
NegTTLNX int
NegTTLTimeout int
NegTTLTemporary int
NegTTLOther int
}
type ResolverRuntimeTuningDeps struct {
EnvInt func(string, int) int
LoadResolverPrecheckLastRun func(path string) int
LoadResolverLiveBatchTarget func(path string, fallback, minV, maxV int) int
LoadResolverLiveBatchNXHeavyPct func(path string, fallback, minV, maxV int) int
}
func BuildResolverRuntimeTuning(in ResolverRuntimeTuningInput, deps ResolverRuntimeTuningDeps) ResolverRuntimeTuning {
envInt := deps.EnvInt
if envInt == nil {
envInt = func(_ string, def int) int { return def }
}
ttl := in.TTL
if ttl <= 0 {
ttl = 24 * 3600
}
if ttl < 60 {
ttl = 60
}
if ttl > 24*3600 {
ttl = 24 * 3600
}
workers := in.Workers
if workers <= 0 {
workers = 80
}
if workers < 1 {
workers = 1
}
if workers > 500 {
workers = 500
}
dnsTimeoutMs := envInt("RESOLVE_DNS_TIMEOUT_MS", 1800)
if dnsTimeoutMs < 300 {
dnsTimeoutMs = 300
}
if dnsTimeoutMs > 5000 {
dnsTimeoutMs = 5000
}
precheckEverySec := envInt("RESOLVE_PRECHECK_EVERY_SEC", 24*3600)
if precheckEverySec < 0 {
precheckEverySec = 0
}
precheckMaxDomains := envInt("RESOLVE_PRECHECK_MAX_DOMAINS", 3000)
if precheckMaxDomains < 0 {
precheckMaxDomains = 0
}
if precheckMaxDomains > 50000 {
precheckMaxDomains = 50000
}
timeoutRecheckMax := envInt("RESOLVE_TIMEOUT_RECHECK_MAX", precheckMaxDomains)
if timeoutRecheckMax < 0 {
timeoutRecheckMax = 0
}
if timeoutRecheckMax > 50000 {
timeoutRecheckMax = 50000
}
liveBatchMin := envInt("RESOLVE_LIVE_BATCH_MIN", 800)
liveBatchMax := envInt("RESOLVE_LIVE_BATCH_MAX", 3000)
liveBatchDefault := envInt("RESOLVE_LIVE_BATCH_DEFAULT", 1800)
if liveBatchMin < 200 {
liveBatchMin = 200
}
if liveBatchMin > 50000 {
liveBatchMin = 50000
}
if liveBatchMax < liveBatchMin {
liveBatchMax = liveBatchMin
}
if liveBatchMax > 50000 {
liveBatchMax = 50000
}
if liveBatchDefault < liveBatchMin {
liveBatchDefault = liveBatchMin
}
if liveBatchDefault > liveBatchMax {
liveBatchDefault = liveBatchMax
}
liveBatchTarget := liveBatchDefault
if deps.LoadResolverLiveBatchTarget != nil {
liveBatchTarget = deps.LoadResolverLiveBatchTarget(in.PrecheckStatePath, liveBatchDefault, liveBatchMin, liveBatchMax)
}
liveBatchNXHeavyMin := envInt("RESOLVE_LIVE_BATCH_NX_HEAVY_MIN_PCT", 5)
liveBatchNXHeavyMax := envInt("RESOLVE_LIVE_BATCH_NX_HEAVY_MAX_PCT", 35)
liveBatchNXHeavyDefault := envInt("RESOLVE_LIVE_BATCH_NX_HEAVY_PCT", 10)
if liveBatchNXHeavyMin < 0 {
liveBatchNXHeavyMin = 0
}
if liveBatchNXHeavyMin > 100 {
liveBatchNXHeavyMin = 100
}
if liveBatchNXHeavyMax < liveBatchNXHeavyMin {
liveBatchNXHeavyMax = liveBatchNXHeavyMin
}
if liveBatchNXHeavyMax > 100 {
liveBatchNXHeavyMax = 100
}
if liveBatchNXHeavyDefault < liveBatchNXHeavyMin {
liveBatchNXHeavyDefault = liveBatchNXHeavyMin
}
if liveBatchNXHeavyDefault > liveBatchNXHeavyMax {
liveBatchNXHeavyDefault = liveBatchNXHeavyMax
}
liveBatchNXHeavyPct := liveBatchNXHeavyDefault
if deps.LoadResolverLiveBatchNXHeavyPct != nil {
liveBatchNXHeavyPct = deps.LoadResolverLiveBatchNXHeavyPct(in.PrecheckStatePath, liveBatchNXHeavyDefault, liveBatchNXHeavyMin, liveBatchNXHeavyMax)
}
precheckLastRun := 0
if deps.LoadResolverPrecheckLastRun != nil {
precheckLastRun = deps.LoadResolverPrecheckLastRun(in.PrecheckStatePath)
}
precheckDue := in.PrecheckEnvForced || in.PrecheckFileForced || (precheckEverySec > 0 && (precheckLastRun <= 0 || in.Now-precheckLastRun >= precheckEverySec))
staleKeepSec := envInt("RESOLVE_STALE_KEEP_SEC", 48*3600)
if staleKeepSec < 0 {
staleKeepSec = 0
}
if staleKeepSec > 7*24*3600 {
staleKeepSec = 7 * 24 * 3600
}
negTTLNX := envInt("RESOLVE_NEGATIVE_TTL_NX", 6*3600)
negTTLTimeout := envInt("RESOLVE_NEGATIVE_TTL_TIMEOUT", 15*60)
negTTLTemporary := envInt("RESOLVE_NEGATIVE_TTL_TEMPORARY", 10*60)
negTTLOther := envInt("RESOLVE_NEGATIVE_TTL_OTHER", 10*60)
clampTTL := func(v int) int {
if v < 0 {
return 0
}
if v > 24*3600 {
return 24 * 3600
}
return v
}
negTTLNX = clampTTL(negTTLNX)
negTTLTimeout = clampTTL(negTTLTimeout)
negTTLTemporary = clampTTL(negTTLTemporary)
negTTLOther = clampTTL(negTTLOther)
return ResolverRuntimeTuning{
TTL: ttl,
Workers: workers,
DNSTimeoutMS: dnsTimeoutMs,
DNSTimeout: time.Duration(dnsTimeoutMs) * time.Millisecond,
PrecheckEverySec: precheckEverySec,
PrecheckMaxDomains: precheckMaxDomains,
TimeoutRecheckMax: timeoutRecheckMax,
LiveBatchMin: liveBatchMin,
LiveBatchMax: liveBatchMax,
LiveBatchTarget: liveBatchTarget,
LiveBatchNXHeavyMin: liveBatchNXHeavyMin,
LiveBatchNXHeavyMax: liveBatchNXHeavyMax,
LiveBatchNXHeavyPct: liveBatchNXHeavyPct,
PrecheckDue: precheckDue,
StaleKeepSec: staleKeepSec,
NegTTLNX: negTTLNX,
NegTTLTimeout: negTTLTimeout,
NegTTLTemporary: negTTLTemporary,
NegTTLOther: negTTLOther,
}
}