refactor(config): restructured with better concurrency and error handling, reduced cross referencing

This commit is contained in:
yusing
2025-10-09 01:02:24 +08:00
parent d08be872a0
commit cab68807ee
25 changed files with 720 additions and 623 deletions

View File

@@ -9,7 +9,9 @@ import (
"github.com/yusing/godoxy/agent/pkg/agent"
"github.com/yusing/godoxy/agent/pkg/certs"
config "github.com/yusing/godoxy/internal/config/types"
"github.com/yusing/godoxy/internal/route/provider"
apitypes "github.com/yusing/goutils/apitypes"
gperr "github.com/yusing/goutils/errs"
)
type VerifyNewAgentRequest struct {
@@ -57,7 +59,7 @@ func Verify(c *gin.Context) {
return
}
nRoutesAdded, err := config.GetInstance().VerifyNewAgent(request.Host, ca, client, request.ContainerRuntime)
nRoutesAdded, err := verifyNewAgent(request.Host, ca, client, request.ContainerRuntime)
if err != nil {
c.JSON(http.StatusBadRequest, apitypes.Error("invalid request", err))
return
@@ -76,3 +78,37 @@ func Verify(c *gin.Context) {
c.JSON(http.StatusOK, apitypes.Success(fmt.Sprintf("Added %d routes", nRoutesAdded)))
}
func verifyNewAgent(host string, ca agent.PEMPair, client agent.PEMPair, containerRuntime agent.ContainerRuntime) (int, gperr.Error) {
cfgState := config.ActiveState.Load()
for _, a := range cfgState.Value().Providers.Agents {
if a.Addr == host {
return 0, gperr.New("agent already exists")
}
}
var agentCfg agent.AgentConfig
agentCfg.Addr = host
agentCfg.Runtime = containerRuntime
err := agentCfg.StartWithCerts(cfgState.Context(), ca.Cert, client.Cert, client.Key)
if err != nil {
return 0, gperr.Wrap(err, "failed to start agent")
}
provider := provider.NewAgentProvider(&agentCfg)
if _, loaded := cfgState.LoadOrStoreProvider(provider.String(), provider); loaded {
return 0, gperr.Errorf("provider %s already exists", provider.String())
}
// agent must be added before loading routes
agent.AddAgent(&agentCfg)
err = provider.LoadRoutes()
if err != nil {
cfgState.DeleteProvider(provider.String())
agent.RemoveAgent(&agentCfg)
return 0, gperr.Wrap(err, "failed to load routes")
}
return provider.NumRoutes(), nil
}

View File

@@ -8,6 +8,8 @@ import (
apitypes "github.com/yusing/godoxy/internal/api/types"
"github.com/yusing/godoxy/internal/homepage"
"github.com/yusing/godoxy/internal/route/routes"
_ "unsafe"
)
type GetFavIconRequest struct {
@@ -62,6 +64,7 @@ func FavIcon(c *gin.Context) {
c.Data(result.StatusCode, result.ContentType(), result.Icon)
}
//go:linkname GetFavIconFromAlias v1.GetFavIconFromAlias
func GetFavIconFromAlias(ctx context.Context, alias string) (homepage.FetchResult, error) {
// try with route.Icon
r, ok := routes.HTTP.Get(alias)

View File

@@ -5,7 +5,7 @@ import (
"github.com/gin-gonic/gin"
apitypes "github.com/yusing/godoxy/internal/api/types"
config "github.com/yusing/godoxy/internal/config/types"
"github.com/yusing/godoxy/internal/config"
)
// @x-id "reload"
@@ -20,7 +20,7 @@ import (
// @Failure 500 {object} apitypes.ErrorResponse
// @Router /reload [post]
func Reload(c *gin.Context) {
if err := config.GetInstance().Reload(); err != nil {
if err := config.Reload(); err != nil {
c.Error(apitypes.InternalServerError(err, "failed to reload config"))
return
}

View File

@@ -5,7 +5,7 @@ import (
"time"
"github.com/gin-gonic/gin"
config "github.com/yusing/godoxy/internal/config/types"
statequery "github.com/yusing/godoxy/internal/config/query"
"github.com/yusing/goutils/http/httpheaders"
"github.com/yusing/goutils/http/websocket"
)
@@ -22,12 +22,11 @@ import (
// @Failure 500 {object} apitypes.ErrorResponse
// @Router /route/providers [get]
func Providers(c *gin.Context) {
cfg := config.GetInstance()
if httpheaders.IsWebsocket(c.Request.Header) {
websocket.PeriodicWrite(c, 5*time.Second, func() (any, error) {
return config.GetInstance().RouteProviderList(), nil
return statequery.RouteProviderList(), nil
})
} else {
c.JSON(http.StatusOK, cfg.RouteProviderList())
c.JSON(http.StatusOK, statequery.RouteProviderList())
}
}

View File

@@ -5,7 +5,7 @@ import (
"github.com/gin-gonic/gin"
apitypes "github.com/yusing/godoxy/internal/api/types"
config "github.com/yusing/godoxy/internal/config/types"
statequery "github.com/yusing/godoxy/internal/config/query"
"github.com/yusing/godoxy/internal/route/routes"
)
@@ -40,7 +40,7 @@ func Route(c *gin.Context) {
}
// also search for excluded routes
route = config.GetInstance().SearchRoute(request.Which)
route = statequery.SearchRoute(request.Which)
if route != nil {
c.JSON(http.StatusOK, route)
return

View File

@@ -5,7 +5,7 @@ import (
"time"
"github.com/gin-gonic/gin"
config "github.com/yusing/godoxy/internal/config/types"
statequery "github.com/yusing/godoxy/internal/config/query"
"github.com/yusing/godoxy/internal/types"
"github.com/yusing/goutils/http/httpheaders"
"github.com/yusing/goutils/http/websocket"
@@ -35,10 +35,9 @@ type ProxyStats struct {
// @Failure 500 {object} apitypes.ErrorResponse
// @Router /stats [get]
func Stats(c *gin.Context) {
cfg := config.GetInstance()
getStats := func() (any, error) {
return map[string]any{
"proxies": cfg.Statistics(),
"proxies": statequery.GetStatistics(),
"uptime": int64(time.Since(startTime).Round(time.Second).Seconds()),
}, nil
}