From dba8441e8a5dd0cd06f1991ea8b35e2eb901e2f9 Mon Sep 17 00:00:00 2001 From: yusing Date: Tue, 30 Dec 2025 12:39:58 +0800 Subject: [PATCH] refactor(routes): add excluded routes to health check and route list - Updated route iteration to include all routes, including excluded ones. - Renamed existing functions for clarity. - Adjusted health info retrieval to reflect changes in route iteration. - Improved route management by adding health monitoring capabilities for excluded routes. --- internal/api/v1/route/routes.go | 12 ++++++------ internal/metrics/uptime/uptime.go | 3 +-- internal/route/route.go | 15 +++++++++++++-- internal/route/routes/query.go | 19 ++++++++++++++----- internal/route/routes/routes.go | 29 ++++++++++++++++++++++------- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/internal/api/v1/route/routes.go b/internal/api/v1/route/routes.go index b65a0297..8dcf2820 100644 --- a/internal/api/v1/route/routes.go +++ b/internal/api/v1/route/routes.go @@ -34,12 +34,12 @@ func Routes(c *gin.Context) { provider := c.Query("provider") if provider == "" { - c.JSON(http.StatusOK, slices.Collect(routes.Iter)) + c.JSON(http.StatusOK, slices.Collect(routes.IterAll)) return } - rts := make([]types.Route, 0, routes.NumRoutes()) - for r := range routes.Iter { + rts := make([]types.Route, 0, routes.NumAllRoutes()) + for r := range routes.IterAll { if r.ProviderName() == provider { rts = append(rts, r) } @@ -51,14 +51,14 @@ func RoutesWS(c *gin.Context) { provider := c.Query("provider") if provider == "" { websocket.PeriodicWrite(c, 3*time.Second, func() (any, error) { - return slices.Collect(routes.Iter), nil + return slices.Collect(routes.IterAll), nil }) return } websocket.PeriodicWrite(c, 3*time.Second, func() (any, error) { - rts := make([]types.Route, 0, routes.NumRoutes()) - for r := range routes.Iter { + rts := make([]types.Route, 0, routes.NumAllRoutes()) + for r := range routes.IterAll { if r.ProviderName() == provider { rts = append(rts, r) } diff --git a/internal/metrics/uptime/uptime.go b/internal/metrics/uptime/uptime.go index 99b7f04a..11dc0718 100644 --- a/internal/metrics/uptime/uptime.go +++ b/internal/metrics/uptime/uptime.go @@ -8,7 +8,6 @@ import ( "github.com/bytedance/sonic" "github.com/lithammer/fuzzysearch/fuzzy" - statequery "github.com/yusing/godoxy/internal/config/query" "github.com/yusing/godoxy/internal/metrics/period" metricsutils "github.com/yusing/godoxy/internal/metrics/utils" "github.com/yusing/godoxy/internal/route/routes" @@ -133,7 +132,7 @@ func (rs RouteStatuses) aggregate(limit int, offset int) Aggregated { r, ok := routes.Get(alias) if !ok { // also search for excluded routes - r = statequery.SearchRoute(alias) + r, ok = routes.Excluded.Get(alias) } if r != nil { displayName = r.DisplayName() diff --git a/internal/route/route.go b/internal/route/route.go index 7d447ea3..420b7c9f 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -24,12 +24,14 @@ import ( "github.com/yusing/godoxy/internal/proxmox" "github.com/yusing/godoxy/internal/serialization" "github.com/yusing/godoxy/internal/types" + "github.com/yusing/godoxy/internal/watcher/health/monitor" gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" "github.com/yusing/goutils/task" "github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/logging/accesslog" + "github.com/yusing/godoxy/internal/route/routes" "github.com/yusing/godoxy/internal/route/rules" rulepresets "github.com/yusing/godoxy/internal/route/rules/presets" route "github.com/yusing/godoxy/internal/route/types" @@ -397,8 +399,17 @@ func (r *Route) start(parent task.Parent) gperr.Error { if err := r.impl.Start(parent); err != nil { return err } - } else { // required by idlewatcher - r.task = parent.Subtask("excluded."+r.Name(), false) + } else { + r.task = parent.Subtask("excluded."+r.Name(), true) + routes.Excluded.Add(r.impl) + r.task.OnCancel("remove_route_from_excluded", func() { + routes.Excluded.Del(r.impl) + }) + if r.UseHealthCheck() { + r.HealthMon = monitor.NewMonitor(r) + err := r.HealthMon.Start(r.task) + return err + } } return nil } diff --git a/internal/route/routes/query.go b/internal/route/routes/query.go index 527774cb..51d9c98a 100644 --- a/internal/route/routes/query.go +++ b/internal/route/routes/query.go @@ -17,17 +17,23 @@ type HealthInfoWithoutDetail struct { Latency time.Duration `json:"latency" swaggertype:"number"` // latency in microseconds } // @name HealthInfoWithoutDetail +// GetHealthInfo returns a map of route name to health info. +// +// The health info is for all routes, including excluded routes. func GetHealthInfo() map[string]HealthInfo { - healthMap := make(map[string]HealthInfo, NumRoutes()) - for r := range Iter { + healthMap := make(map[string]HealthInfo, NumAllRoutes()) + for r := range IterAll { healthMap[r.Name()] = getHealthInfo(r) } return healthMap } +// GetHealthInfoWithoutDetail returns a map of route name to health info without detail. +// +// The health info is for all routes, including excluded routes. func GetHealthInfoWithoutDetail() map[string]HealthInfoWithoutDetail { - healthMap := make(map[string]HealthInfoWithoutDetail, NumRoutes()) - for r := range Iter { + healthMap := make(map[string]HealthInfoWithoutDetail, NumAllRoutes()) + for r := range IterAll { healthMap[r.Name()] = getHealthInfoWithoutDetail(r) } return healthMap @@ -67,9 +73,12 @@ func getHealthInfoWithoutDetail(r types.Route) HealthInfoWithoutDetail { } } +// ByProvider returns a map of provider name to routes. +// +// The routes are all routes, including excluded routes. func ByProvider() map[string][]types.Route { rts := make(map[string][]types.Route) - for r := range Iter { + for r := range IterAll { rts[r.ProviderName()] = append(rts[r.ProviderName()], r) } return rts diff --git a/internal/route/routes/routes.go b/internal/route/routes/routes.go index 4c325124..61034610 100644 --- a/internal/route/routes/routes.go +++ b/internal/route/routes/routes.go @@ -8,9 +8,11 @@ import ( var ( HTTP = pool.New[types.HTTPRoute]("http_routes") Stream = pool.New[types.StreamRoute]("stream_routes") + + Excluded = pool.New[types.Route]("excluded_routes") ) -func Iter(yield func(r types.Route) bool) { +func IterActive(yield func(r types.Route) bool) { for _, r := range HTTP.Iter { if !yield(r) { break @@ -23,26 +25,36 @@ func Iter(yield func(r types.Route) bool) { } } -func IterKV(yield func(alias string, r types.Route) bool) { - for k, r := range HTTP.Iter { - if !yield(k, r) { +func IterAll(yield func(r types.Route) bool) { + for _, r := range HTTP.Iter { + if !yield(r) { break } } - for k, r := range Stream.Iter { - if !yield(k, r) { + for _, r := range Stream.Iter { + if !yield(r) { + break + } + } + for _, r := range Excluded.Iter { + if !yield(r) { break } } } -func NumRoutes() int { +func NumActiveRoutes() int { return HTTP.Size() + Stream.Size() } +func NumAllRoutes() int { + return HTTP.Size() + Stream.Size() + Excluded.Size() +} + func Clear() { HTTP.Clear() Stream.Clear() + Excluded.Clear() } func GetHTTPRouteOrExact(alias, host string) (types.HTTPRoute, bool) { @@ -54,6 +66,9 @@ func GetHTTPRouteOrExact(alias, host string) (types.HTTPRoute, bool) { return HTTP.Get(host) } +// Get returns the route with the given alias. +// +// It does not return excluded routes. func Get(alias string) (types.Route, bool) { if r, ok := HTTP.Get(alias); ok { return r, true