Clash.Meta/adapter/provider/healthcheck.go

92 lines
1.5 KiB
Go
Raw Normal View History

2019-12-08 12:17:24 +08:00
package provider
import (
"context"
"sync"
2019-12-08 12:17:24 +08:00
"time"
C "github.com/Dreamacro/clash/constant"
"go.uber.org/atomic"
2019-12-08 12:17:24 +08:00
)
const (
defaultURLTestTimeout = time.Second * 5
)
type HealthCheckOption struct {
URL string
Interval uint
}
type HealthCheck struct {
url string
proxies []C.Proxy
interval uint
lazy bool
lastTouch *atomic.Int64
done chan struct{}
2019-12-08 12:17:24 +08:00
}
func (hc *HealthCheck) process() {
ticker := time.NewTicker(time.Duration(hc.interval) * time.Second)
2019-12-08 12:17:24 +08:00
go hc.check()
for {
select {
case <-ticker.C:
now := time.Now().Unix()
if !hc.lazy || now-hc.lastTouch.Load() < int64(hc.interval) {
hc.check()
}
case <-hc.done:
ticker.Stop()
return
}
2019-12-08 12:17:24 +08:00
}
}
func (hc *HealthCheck) setProxy(proxies []C.Proxy) {
hc.proxies = proxies
}
func (hc *HealthCheck) auto() bool {
return hc.interval != 0
}
func (hc *HealthCheck) touch() {
hc.lastTouch.Store(time.Now().Unix())
}
func (hc *HealthCheck) check() {
2019-12-08 12:17:24 +08:00
ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout)
wg := &sync.WaitGroup{}
2019-12-08 12:17:24 +08:00
for _, proxy := range hc.proxies {
wg.Add(1)
go func(p C.Proxy) {
p.URLTest(ctx, hc.url)
wg.Done()
}(proxy)
2019-12-08 12:17:24 +08:00
}
wg.Wait()
2019-12-08 12:17:24 +08:00
cancel()
}
func (hc *HealthCheck) close() {
hc.done <- struct{}{}
2019-12-08 12:17:24 +08:00
}
func NewHealthCheck(proxies []C.Proxy, url string, interval uint, lazy bool) *HealthCheck {
return &HealthCheck{
proxies: proxies,
url: url,
interval: interval,
lazy: lazy,
lastTouch: atomic.NewInt64(0),
done: make(chan struct{}, 1),
2019-12-08 12:17:24 +08:00
}
}