Feature: add lazy
for proxy group and provider
This commit is contained in:
@ -5,6 +5,8 @@ import (
|
||||
"time"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
||||
"go.uber.org/atomic"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -17,10 +19,12 @@ type HealthCheckOption struct {
|
||||
}
|
||||
|
||||
type HealthCheck struct {
|
||||
url string
|
||||
proxies []C.Proxy
|
||||
interval uint
|
||||
done chan struct{}
|
||||
url string
|
||||
proxies []C.Proxy
|
||||
interval uint
|
||||
lazy bool
|
||||
lastTouch *atomic.Int64
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func (hc *HealthCheck) process() {
|
||||
@ -30,7 +34,10 @@ func (hc *HealthCheck) process() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
hc.check()
|
||||
now := time.Now().Unix()
|
||||
if !hc.lazy || now-hc.lastTouch.Load() < int64(hc.interval) {
|
||||
hc.check()
|
||||
}
|
||||
case <-hc.done:
|
||||
ticker.Stop()
|
||||
return
|
||||
@ -46,6 +53,10 @@ func (hc *HealthCheck) auto() bool {
|
||||
return hc.interval != 0
|
||||
}
|
||||
|
||||
func (hc *HealthCheck) touch() {
|
||||
hc.lastTouch.Store(time.Now().Unix())
|
||||
}
|
||||
|
||||
func (hc *HealthCheck) check() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout)
|
||||
for _, proxy := range hc.proxies {
|
||||
@ -60,11 +71,13 @@ func (hc *HealthCheck) close() {
|
||||
hc.done <- struct{}{}
|
||||
}
|
||||
|
||||
func NewHealthCheck(proxies []C.Proxy, url string, interval uint) *HealthCheck {
|
||||
func NewHealthCheck(proxies []C.Proxy, url string, interval uint, lazy bool) *HealthCheck {
|
||||
return &HealthCheck{
|
||||
proxies: proxies,
|
||||
url: url,
|
||||
interval: interval,
|
||||
done: make(chan struct{}, 1),
|
||||
proxies: proxies,
|
||||
url: url,
|
||||
interval: interval,
|
||||
lazy: lazy,
|
||||
lastTouch: atomic.NewInt64(0),
|
||||
done: make(chan struct{}, 1),
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ type healthCheckSchema struct {
|
||||
Enable bool `provider:"enable"`
|
||||
URL string `provider:"url"`
|
||||
Interval int `provider:"interval"`
|
||||
Lazy bool `provider:"lazy,omitempty"`
|
||||
}
|
||||
|
||||
type proxyProviderSchema struct {
|
||||
@ -30,7 +31,11 @@ type proxyProviderSchema struct {
|
||||
func ParseProxyProvider(name string, mapping map[string]interface{}) (ProxyProvider, error) {
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
|
||||
|
||||
schema := &proxyProviderSchema{}
|
||||
schema := &proxyProviderSchema{
|
||||
HealthCheck: healthCheckSchema{
|
||||
Lazy: true,
|
||||
},
|
||||
}
|
||||
if err := decoder.Decode(mapping, schema); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -39,7 +44,7 @@ func ParseProxyProvider(name string, mapping map[string]interface{}) (ProxyProvi
|
||||
if schema.HealthCheck.Enable {
|
||||
hcInterval = uint(schema.HealthCheck.Interval)
|
||||
}
|
||||
hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, hcInterval)
|
||||
hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, hcInterval, schema.HealthCheck.Lazy)
|
||||
|
||||
path := C.Path.Resolve(schema.Path)
|
||||
|
||||
|
@ -50,6 +50,9 @@ type Provider interface {
|
||||
type ProxyProvider interface {
|
||||
Provider
|
||||
Proxies() []C.Proxy
|
||||
// ProxiesWithTouch is used to inform the provider that the proxy is actually being used while getting the list of proxies.
|
||||
// Commonly used in Dial and DialUDP
|
||||
ProxiesWithTouch() []C.Proxy
|
||||
HealthCheck()
|
||||
}
|
||||
|
||||
@ -112,6 +115,11 @@ func (pp *proxySetProvider) Proxies() []C.Proxy {
|
||||
return pp.proxies
|
||||
}
|
||||
|
||||
func (pp *proxySetProvider) ProxiesWithTouch() []C.Proxy {
|
||||
pp.healthCheck.touch()
|
||||
return pp.Proxies()
|
||||
}
|
||||
|
||||
func proxiesParse(buf []byte) (interface{}, error) {
|
||||
schema := &ProxySchema{}
|
||||
|
||||
@ -223,6 +231,11 @@ func (cp *compatibleProvider) Proxies() []C.Proxy {
|
||||
return cp.proxies
|
||||
}
|
||||
|
||||
func (cp *compatibleProvider) ProxiesWithTouch() []C.Proxy {
|
||||
cp.healthCheck.touch()
|
||||
return cp.Proxies()
|
||||
}
|
||||
|
||||
func stopCompatibleProvider(pd *CompatibleProvider) {
|
||||
pd.healthCheck.close()
|
||||
}
|
||||
|
Reference in New Issue
Block a user