From 767aa182b9116902e5f7f0f7d8e98ad7043dcd65 Mon Sep 17 00:00:00 2001 From: wzdnzd Date: Wed, 7 Jun 2023 11:04:03 +0800 Subject: [PATCH] When testing the delay through REST API, determine whether to store the delay data based on certain conditions instead of discarding it directly (#609) --- adapter/adapter.go | 35 ++++++++++++++++++++++++++++++--- adapter/outboundgroup/parser.go | 17 +++++++++------- adapter/provider/healthcheck.go | 10 +++++++--- constant/adapters.go | 7 ++++--- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/adapter/adapter.go b/adapter/adapter.go index 32fd2b77..32b6bae0 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -34,6 +34,7 @@ type Proxy struct { C.ProxyAdapter history *queue.Queue[C.DelayHistory] alive *atomic.Bool + url string extra map[string]*extraProxyState } @@ -112,14 +113,14 @@ func (p *Proxy) DelayHistoryForTestUrl(url string) []C.DelayHistory { func (p *Proxy) ExtraDelayHistory() map[string][]C.DelayHistory { extra := map[string][]C.DelayHistory{} if p.extra != nil && len(p.extra) != 0 { - for url, option := range p.extra { + for testUrl, option := range p.extra { histories := []C.DelayHistory{} queueM := option.history.Copy() for _, item := range queueM { histories = append(histories, item) } - extra[url] = histories + extra[testUrl] = histories } } return extra @@ -187,6 +188,8 @@ func (p *Proxy) MarshalJSON() ([]byte, error) { func (p *Proxy) URLTest(ctx context.Context, url string, expectedStatus utils.IntRanges[uint16], store C.DelayHistoryStoreType) (t uint16, err error) { defer func() { alive := err == nil + store = p.determineFinalStoreType(store, url) + switch store { case C.OriginalHistory: p.alive.Store(alive) @@ -198,6 +201,11 @@ func (p *Proxy) URLTest(ctx context.Context, url string, expectedStatus utils.In if p.history.Len() > defaultHistoriesNum { p.history.Pop() } + + // test URL configured by the proxy provider + if len(p.url) == 0 { + p.url = url + } case C.ExtraHistory: record := C.DelayHistory{Time: time.Now()} if alive { @@ -297,7 +305,7 @@ func (p *Proxy) URLTest(ctx context.Context, url string, expectedStatus utils.In } func NewProxy(adapter C.ProxyAdapter) *Proxy { - return &Proxy{adapter, queue.New[C.DelayHistory](defaultHistoriesNum), atomic.NewBool(true), map[string]*extraProxyState{}} + return &Proxy{adapter, queue.New[C.DelayHistory](defaultHistoriesNum), atomic.NewBool(true), "", map[string]*extraProxyState{}} } func urlToMetadata(rawURL string) (addr C.Metadata, err error) { @@ -326,3 +334,24 @@ func urlToMetadata(rawURL string) (addr C.Metadata, err error) { } return } + +func (p *Proxy) determineFinalStoreType(store C.DelayHistoryStoreType, url string) C.DelayHistoryStoreType { + if store != C.DropHistory { + return store + } + + if len(p.url) == 0 || url == p.url { + return C.OriginalHistory + } + + if p.extra == nil { + store = C.ExtraHistory + } else { + if _, ok := p.extra[url]; ok { + store = C.ExtraHistory + } else if len(p.extra) < 2*C.DefaultMaxHealthCheckUrlNum { + store = C.ExtraHistory + } + } + return store +} diff --git a/adapter/outboundgroup/parser.go b/adapter/outboundgroup/parser.go index 684960b3..a8bdc557 100644 --- a/adapter/outboundgroup/parser.go +++ b/adapter/outboundgroup/parser.go @@ -17,7 +17,6 @@ var ( errFormat = errors.New("format error") errType = errors.New("unsupported type") errMissProxy = errors.New("`use` or `proxies` missing") - errMissHealthCheck = errors.New("`url` or `interval` missing") errDuplicateProvider = errors.New("duplicate provider name") ) @@ -81,11 +80,8 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide return nil, fmt.Errorf("%s: %w", groupName, errDuplicateProvider) } - hc := provider.NewHealthCheck(ps, "", 0, true, nil) - pd, err := provider.NewCompatibleProvider(groupName, ps, hc) - if err != nil { - return nil, fmt.Errorf("%s: %w", groupName, err) - } + var url string + var interval uint // select don't need health check if groupOption.Type != "select" && groupOption.Type != "relay" { @@ -97,7 +93,14 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide groupOption.Interval = 300 } - pd.RegisterHealthCheckTask(groupOption.URL, expectedStatus, "", uint(groupOption.Interval)) + url = groupOption.URL + interval = uint(groupOption.Interval) + } + + hc := provider.NewHealthCheck(ps, url, interval, true, expectedStatus) + pd, err := provider.NewCompatibleProvider(groupName, ps, hc) + if err != nil { + return nil, fmt.Errorf("%s: %w", groupName, err) } providers = append(providers, pd) diff --git a/adapter/provider/healthcheck.go b/adapter/provider/healthcheck.go index 330e306e..35327b1c 100644 --- a/adapter/provider/healthcheck.go +++ b/adapter/provider/healthcheck.go @@ -18,7 +18,6 @@ import ( const ( defaultURLTestTimeout = time.Second * 5 - defaultMaxTestUrlNum = 6 ) type HealthCheckOption struct { @@ -105,8 +104,8 @@ func (hc *HealthCheck) registerHealthCheckTask(url string, expectedStatus utils. } // due to the time-consuming nature of health checks, a maximum of defaultMaxTestURLNum URLs can be set for testing - if len(hc.extra) > defaultMaxTestUrlNum { - log.Debugln("skip add url: %s to health check because it has reached the maximum limit: %d", url, defaultMaxTestUrlNum) + if len(hc.extra) > C.DefaultMaxHealthCheckUrlNum { + log.Debugln("skip add url: %s to health check because it has reached the maximum limit: %d", url, C.DefaultMaxHealthCheckUrlNum) return } @@ -220,6 +219,11 @@ func (hc *HealthCheck) close() { } func NewHealthCheck(proxies []C.Proxy, url string, interval uint, lazy bool, expectedStatus utils.IntRanges[uint16]) *HealthCheck { + if len(url) == 0 { + interval = 0 + expectedStatus = nil + } + return &HealthCheck{ proxies: proxies, url: url, diff --git a/constant/adapters.go b/constant/adapters.go index a55c2d18..a3796ef7 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -41,9 +41,10 @@ const ( ) const ( - DefaultTCPTimeout = 5 * time.Second - DefaultUDPTimeout = DefaultTCPTimeout - DefaultTLSTimeout = DefaultTCPTimeout + DefaultTCPTimeout = 5 * time.Second + DefaultUDPTimeout = DefaultTCPTimeout + DefaultTLSTimeout = DefaultTCPTimeout + DefaultMaxHealthCheckUrlNum = 16 ) var ErrNotSupport = errors.New("no support")