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.
This commit is contained in:
yusing
2025-12-30 12:39:58 +08:00
parent 44fc678496
commit dba8441e8a
5 changed files with 56 additions and 22 deletions

View File

@@ -34,12 +34,12 @@ func Routes(c *gin.Context) {
provider := c.Query("provider") provider := c.Query("provider")
if provider == "" { if provider == "" {
c.JSON(http.StatusOK, slices.Collect(routes.Iter)) c.JSON(http.StatusOK, slices.Collect(routes.IterAll))
return return
} }
rts := make([]types.Route, 0, routes.NumRoutes()) rts := make([]types.Route, 0, routes.NumAllRoutes())
for r := range routes.Iter { for r := range routes.IterAll {
if r.ProviderName() == provider { if r.ProviderName() == provider {
rts = append(rts, r) rts = append(rts, r)
} }
@@ -51,14 +51,14 @@ func RoutesWS(c *gin.Context) {
provider := c.Query("provider") provider := c.Query("provider")
if provider == "" { if provider == "" {
websocket.PeriodicWrite(c, 3*time.Second, func() (any, error) { websocket.PeriodicWrite(c, 3*time.Second, func() (any, error) {
return slices.Collect(routes.Iter), nil return slices.Collect(routes.IterAll), nil
}) })
return return
} }
websocket.PeriodicWrite(c, 3*time.Second, func() (any, error) { websocket.PeriodicWrite(c, 3*time.Second, func() (any, error) {
rts := make([]types.Route, 0, routes.NumRoutes()) rts := make([]types.Route, 0, routes.NumAllRoutes())
for r := range routes.Iter { for r := range routes.IterAll {
if r.ProviderName() == provider { if r.ProviderName() == provider {
rts = append(rts, r) rts = append(rts, r)
} }

View File

@@ -8,7 +8,6 @@ import (
"github.com/bytedance/sonic" "github.com/bytedance/sonic"
"github.com/lithammer/fuzzysearch/fuzzy" "github.com/lithammer/fuzzysearch/fuzzy"
statequery "github.com/yusing/godoxy/internal/config/query"
"github.com/yusing/godoxy/internal/metrics/period" "github.com/yusing/godoxy/internal/metrics/period"
metricsutils "github.com/yusing/godoxy/internal/metrics/utils" metricsutils "github.com/yusing/godoxy/internal/metrics/utils"
"github.com/yusing/godoxy/internal/route/routes" "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) r, ok := routes.Get(alias)
if !ok { if !ok {
// also search for excluded routes // also search for excluded routes
r = statequery.SearchRoute(alias) r, ok = routes.Excluded.Get(alias)
} }
if r != nil { if r != nil {
displayName = r.DisplayName() displayName = r.DisplayName()

View File

@@ -24,12 +24,14 @@ import (
"github.com/yusing/godoxy/internal/proxmox" "github.com/yusing/godoxy/internal/proxmox"
"github.com/yusing/godoxy/internal/serialization" "github.com/yusing/godoxy/internal/serialization"
"github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/types"
"github.com/yusing/godoxy/internal/watcher/health/monitor"
gperr "github.com/yusing/goutils/errs" gperr "github.com/yusing/goutils/errs"
strutils "github.com/yusing/goutils/strings" strutils "github.com/yusing/goutils/strings"
"github.com/yusing/goutils/task" "github.com/yusing/goutils/task"
"github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/common"
"github.com/yusing/godoxy/internal/logging/accesslog" "github.com/yusing/godoxy/internal/logging/accesslog"
"github.com/yusing/godoxy/internal/route/routes"
"github.com/yusing/godoxy/internal/route/rules" "github.com/yusing/godoxy/internal/route/rules"
rulepresets "github.com/yusing/godoxy/internal/route/rules/presets" rulepresets "github.com/yusing/godoxy/internal/route/rules/presets"
route "github.com/yusing/godoxy/internal/route/types" 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 { if err := r.impl.Start(parent); err != nil {
return err return err
} }
} else { // required by idlewatcher } else {
r.task = parent.Subtask("excluded."+r.Name(), false) 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 return nil
} }

View File

@@ -17,17 +17,23 @@ type HealthInfoWithoutDetail struct {
Latency time.Duration `json:"latency" swaggertype:"number"` // latency in microseconds Latency time.Duration `json:"latency" swaggertype:"number"` // latency in microseconds
} // @name HealthInfoWithoutDetail } // @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 { func GetHealthInfo() map[string]HealthInfo {
healthMap := make(map[string]HealthInfo, NumRoutes()) healthMap := make(map[string]HealthInfo, NumAllRoutes())
for r := range Iter { for r := range IterAll {
healthMap[r.Name()] = getHealthInfo(r) healthMap[r.Name()] = getHealthInfo(r)
} }
return healthMap 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 { func GetHealthInfoWithoutDetail() map[string]HealthInfoWithoutDetail {
healthMap := make(map[string]HealthInfoWithoutDetail, NumRoutes()) healthMap := make(map[string]HealthInfoWithoutDetail, NumAllRoutes())
for r := range Iter { for r := range IterAll {
healthMap[r.Name()] = getHealthInfoWithoutDetail(r) healthMap[r.Name()] = getHealthInfoWithoutDetail(r)
} }
return healthMap 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 { func ByProvider() map[string][]types.Route {
rts := make(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) rts[r.ProviderName()] = append(rts[r.ProviderName()], r)
} }
return rts return rts

View File

@@ -8,9 +8,11 @@ import (
var ( var (
HTTP = pool.New[types.HTTPRoute]("http_routes") HTTP = pool.New[types.HTTPRoute]("http_routes")
Stream = pool.New[types.StreamRoute]("stream_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 { for _, r := range HTTP.Iter {
if !yield(r) { if !yield(r) {
break break
@@ -23,26 +25,36 @@ func Iter(yield func(r types.Route) bool) {
} }
} }
func IterKV(yield func(alias string, r types.Route) bool) { func IterAll(yield func(r types.Route) bool) {
for k, r := range HTTP.Iter { for _, r := range HTTP.Iter {
if !yield(k, r) { if !yield(r) {
break break
} }
} }
for k, r := range Stream.Iter { for _, r := range Stream.Iter {
if !yield(k, r) { if !yield(r) {
break
}
}
for _, r := range Excluded.Iter {
if !yield(r) {
break break
} }
} }
} }
func NumRoutes() int { func NumActiveRoutes() int {
return HTTP.Size() + Stream.Size() return HTTP.Size() + Stream.Size()
} }
func NumAllRoutes() int {
return HTTP.Size() + Stream.Size() + Excluded.Size()
}
func Clear() { func Clear() {
HTTP.Clear() HTTP.Clear()
Stream.Clear() Stream.Clear()
Excluded.Clear()
} }
func GetHTTPRouteOrExact(alias, host string) (types.HTTPRoute, bool) { func GetHTTPRouteOrExact(alias, host string) (types.HTTPRoute, bool) {
@@ -54,6 +66,9 @@ func GetHTTPRouteOrExact(alias, host string) (types.HTTPRoute, bool) {
return HTTP.Get(host) 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) { func Get(alias string) (types.Route, bool) {
if r, ok := HTTP.Get(alias); ok { if r, ok := HTTP.Get(alias); ok {
return r, true return r, true