From e107b18954bd0596418aa8d8d63ec17d053059db Mon Sep 17 00:00:00 2001 From: gVisor bot Date: Sat, 25 Jun 2022 08:53:04 +0800 Subject: [PATCH] chore: healthcheck only once check at same time --- adapter/outboundgroup/groupbase.go | 4 ++-- adapter/provider/healthcheck.go | 29 ++++++++++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/adapter/outboundgroup/groupbase.go b/adapter/outboundgroup/groupbase.go index 42b61dd4..5ec0c999 100644 --- a/adapter/outboundgroup/groupbase.go +++ b/adapter/outboundgroup/groupbase.go @@ -111,11 +111,11 @@ func (gb *GroupBase) URLTest(ctx context.Context, url string) (map[string]uint16 wg.Add(1) go func() { delay, err := proxy.URLTest(ctx, url) - lock.Lock() if err == nil { + lock.Lock() mp[proxy.Name()] = delay + lock.Unlock() } - lock.Unlock() wg.Done() }() diff --git a/adapter/provider/healthcheck.go b/adapter/provider/healthcheck.go index cc664c9e..8e736f6c 100644 --- a/adapter/provider/healthcheck.go +++ b/adapter/provider/healthcheck.go @@ -2,6 +2,7 @@ package provider import ( "context" + "github.com/Dreamacro/clash/common/singledo" "time" "github.com/Dreamacro/clash/common/batch" @@ -26,6 +27,7 @@ type HealthCheck struct { lazy bool lastTouch *atomic.Int64 done chan struct{} + singleDo *singledo.Single[struct{}] } func (hc *HealthCheck) process() { @@ -63,17 +65,21 @@ func (hc *HealthCheck) touch() { } func (hc *HealthCheck) check() { - b, _ := batch.New[bool](context.Background(), batch.WithConcurrencyNum[bool](10)) - for _, proxy := range hc.proxies { - p := proxy - b.Go(p.Name(), func() (bool, error) { - ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) - defer cancel() - _, _ = p.URLTest(ctx, hc.url) - return false, nil - }) - } - b.Wait() + _, _, _ = hc.singleDo.Do(func() (struct{}, error) { + b, _ := batch.New[bool](context.Background(), batch.WithConcurrencyNum[bool](10)) + for _, proxy := range hc.proxies { + p := proxy + b.Go(p.Name(), func() (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) + defer cancel() + _, _ = p.URLTest(ctx, hc.url) + return false, nil + }) + } + + b.Wait() + return struct{}{}, nil + }) } func (hc *HealthCheck) close() { @@ -88,5 +94,6 @@ func NewHealthCheck(proxies []C.Proxy, url string, interval uint, lazy bool) *He lazy: lazy, lastTouch: atomic.NewInt64(0), done: make(chan struct{}, 1), + singleDo: singledo.NewSingle[struct{}](time.Second), } }