refactor(errs): migrate from gperr.Error to standard Go error interface

This is a large-scale refactoring across the codebase that replaces the custom
`gperr.Error` type with Go's standard `error` interface. The changes include:

- Replacing `gperr.Error` return types with `error` in function signatures
- Using `errors.New()` and `fmt.Errorf()` instead of `gperr.New()` and `gperr.Errorf()`
- Using `%w` format verb for error wrapping instead of `.With()` method
- Replacing `gperr.Subject()` calls with `gperr.PrependSubject()`
- Converting error logging from `gperr.Log*()` functions to zerolog's `.Err().Msg()` pattern
- Update NewLogger to handle multiline error message
- Updating `goutils` submodule to latest commit

This refactoring aligns with Go idioms and removes the dependency on
custom error handling abstractions in favor of standard library patterns.
This commit is contained in:
yusing
2026-02-08 12:07:36 +08:00
parent 7eb2a78041
commit 6da7227f9b
118 changed files with 572 additions and 563 deletions

View File

@@ -39,7 +39,7 @@ type ProviderImpl interface {
fmt.Stringer
ShortName() string
IsExplicitOnly() bool
loadRoutesImpl() (route.Routes, gperr.Error)
loadRoutesImpl() (route.Routes, error)
NewWatcher() W.Watcher
Logger() *zerolog.Logger
}
@@ -62,8 +62,8 @@ func NewAgentProvider(cfg *agent.AgentConfig) *Provider
```go
func (p *Provider) GetType() provider.Type
func (p *Provider) Start(parent task.Parent) gperr.Error
func (p *Provider) LoadRoutes() gperr.Error
func (p *Provider) Start(parent task.Parent) error
func (p *Provider) LoadRoutes() error
func (p *Provider) IterRoutes(yield func(string, types.Route) bool)
func (p *Provider) GetRoute(alias string) (types.Route, bool)
func (p *Provider) FindService(project, service string) (types.Route, bool)
@@ -80,8 +80,8 @@ classDiagram
+t provider.Type
+routes route.Routes
+watcher W.Watcher
+Start(parent) gperr.Error
+LoadRoutes() gperr.Error
+Start(parent) error
+LoadRoutes() error
+IterRoutes(yield)
}
@@ -90,7 +90,7 @@ classDiagram
+String() string
+ShortName() string
+IsExplicitOnly() bool
+loadRoutesImpl() (route.Routes, gperr.Error)
+loadRoutesImpl() (route.Routes, error)
+NewWatcher() W.Watcher
+Logger() *zerolog.Logger
}
@@ -99,20 +99,20 @@ classDiagram
+name string
+dockerCfg types.DockerProviderConfig
+ShortName() string
+loadRoutesImpl() (route.Routes, gperr.Error)
+loadRoutesImpl() (route.Routes, error)
}
class FileProviderImpl {
+filename string
+ShortName() string
+loadRoutesImpl() (route.Routes, gperr.Error)
+loadRoutesImpl() (route.Routes, error)
}
class AgentProviderImpl {
+*agent.AgentConfig
+docker DockerProviderImpl
+ShortName() string
+loadRoutesImpl() (route.Routes, gperr.Error)
+loadRoutesImpl() (route.Routes, error)
}
Provider --> ProviderImpl : wraps

View File

@@ -5,7 +5,6 @@ import (
"github.com/yusing/godoxy/agent/pkg/agent"
"github.com/yusing/godoxy/internal/route"
"github.com/yusing/godoxy/internal/watcher"
gperr "github.com/yusing/goutils/errs"
)
type AgentProvider struct {
@@ -25,7 +24,7 @@ func (p *AgentProvider) IsExplicitOnly() bool {
return p.docker.IsExplicitOnly()
}
func (p *AgentProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
func (p *AgentProvider) loadRoutesImpl() (route.Routes, error) {
return p.docker.loadRoutesImpl()
}

View File

@@ -58,13 +58,13 @@ func (p *DockerProvider) NewWatcher() watcher.Watcher {
return watcher.NewDockerWatcher(p.dockerCfg)
}
func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
func (p *DockerProvider) loadRoutesImpl() (route.Routes, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
containers, err := docker.ListContainers(ctx, p.dockerCfg)
if err != nil {
return nil, gperr.Wrap(err)
return nil, err
}
errs := gperr.NewBuilder("")
@@ -74,21 +74,21 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
container := docker.FromDocker(&c, p.dockerCfg)
if container.Errors != nil {
errs.Add(gperr.PrependSubject(container.ContainerName, container.Errors))
errs.AddSubject(container.Errors, container.ContainerName)
continue
}
if container.IsHostNetworkMode {
err := docker.UpdatePorts(ctx, container)
if err != nil {
errs.Add(gperr.PrependSubject(container.ContainerName, err))
errs.AddSubject(err, container.ContainerName)
continue
}
}
newEntries, err := p.routesFromContainerLabels(container)
if err != nil {
errs.Add(err.Subject(container.ContainerName))
errs.AddSubject(err, container.ContainerName)
}
for k, v := range newEntries {
if conflict, ok := routes[k]; ok {
@@ -97,7 +97,7 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
Addf("container %s", container.ContainerName).
Addf("conflicting container %s", conflict.Container.ContainerName)
if conflict.ShouldExclude() || v.ShouldExclude() {
gperr.LogWarn("skipping conflicting route", err)
log.Warn().Err(err).Msg("skipping conflicting route")
} else {
errs.Add(err)
}
@@ -112,7 +112,7 @@ func (p *DockerProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
// Returns a list of proxy entries for a container.
// Always non-nil.
func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (route.Routes, gperr.Error) {
func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (route.Routes, error) {
if !container.IsExplicit && p.IsExplicitOnly() {
return make(route.Routes, 0), nil
}
@@ -150,7 +150,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (
panic(fmt.Errorf("invalid entry map type %T", entryMapAny))
}
if err := yaml.Unmarshal([]byte(yamlStr), &entryMap); err != nil {
errs.Add(gperr.Wrap(err).Subject(alias))
errs.AddSubject(err, alias)
continue
}
}
@@ -185,7 +185,7 @@ func (p *DockerProvider) routesFromContainerLabels(container *types.Container) (
// deserialize map into entry object
err := serialization.MapUnmarshalValidate(entryMap, r)
if err != nil {
errs.Add(err.Subject(alias))
errs.AddSubject(err, alias)
} else {
routes[alias] = r
}

View File

@@ -81,7 +81,7 @@ func (handler *EventHandler) match(event watcher.Event, route *route.Route) bool
func (handler *EventHandler) Add(parent task.Parent, route *route.Route) {
err := handler.provider.startRoute(parent, route)
if err != nil {
handler.errs.Add(err.Subject("add"))
handler.errs.AddSubjectf(err, "add")
}
}
@@ -93,7 +93,7 @@ func (handler *EventHandler) Update(parent task.Parent, oldRoute *route.Route, n
oldRoute.FinishAndWait("route update")
err := handler.provider.startRoute(parent, newRoute)
if err != nil {
handler.errs.Add(err.Subject("update"))
handler.errs.AddSubjectf(err, "update")
}
}

View File

@@ -12,7 +12,6 @@ import (
"github.com/yusing/godoxy/internal/route"
"github.com/yusing/godoxy/internal/serialization"
W "github.com/yusing/godoxy/internal/watcher"
gperr "github.com/yusing/goutils/errs"
)
type FileProvider struct {
@@ -34,7 +33,7 @@ func FileProviderImpl(filename string) (ProviderImpl, error) {
return impl, nil
}
func removeXPrefix(m map[string]any) gperr.Error {
func removeXPrefix(m map[string]any) error {
for alias := range m {
if strings.HasPrefix(alias, "x-") {
delete(m, alias)
@@ -43,12 +42,12 @@ func removeXPrefix(m map[string]any) gperr.Error {
return nil
}
func validate(data []byte) (routes route.Routes, err gperr.Error) {
func validate(data []byte) (routes route.Routes, err error) {
err = serialization.UnmarshalValidate(data, &routes, yaml.Unmarshal, removeXPrefix)
return routes, err
}
func Validate(data []byte) (err gperr.Error) {
func Validate(data []byte) (err error) {
_, err = validate(data)
return err
}
@@ -69,16 +68,16 @@ func (p *FileProvider) Logger() *zerolog.Logger {
return &p.l
}
func (p *FileProvider) loadRoutesImpl() (route.Routes, gperr.Error) {
func (p *FileProvider) loadRoutesImpl() (route.Routes, error) {
data, err := os.ReadFile(p.path)
if err != nil {
return nil, gperr.Wrap(err)
return nil, err
}
routes, err := validate(data)
if err != nil && len(routes) == 0 {
return nil, gperr.Wrap(err)
return nil, err
}
return routes, gperr.Wrap(err)
return routes, err
}
func (p *FileProvider) NewWatcher() W.Watcher {

View File

@@ -34,7 +34,7 @@ type (
fmt.Stringer
ShortName() string
IsExplicitOnly() bool
loadRoutesImpl() (route.Routes, gperr.Error)
loadRoutesImpl() (route.Routes, error)
NewWatcher() W.Watcher
Logger() *zerolog.Logger
}
@@ -96,7 +96,7 @@ func (p *Provider) MarshalText() ([]byte, error) {
}
// Start implements task.TaskStarter.
func (p *Provider) Start(parent task.Parent) gperr.Error {
func (p *Provider) Start(parent task.Parent) error {
errs := gperr.NewGroup("routes error")
t := parent.Subtask("provider."+p.String(), false)
@@ -124,8 +124,8 @@ func (p *Provider) Start(parent task.Parent) gperr.Error {
handler.Handle(t, events)
handler.Log()
},
func(err gperr.Error) {
gperr.LogError("event error", err, p.Logger())
func(err error) {
p.Logger().Err(err).Msg("event error")
},
)
eventQueue.Start(p.watcher.Events(t.Context()))
@@ -136,7 +136,7 @@ func (p *Provider) Start(parent task.Parent) gperr.Error {
return nil
}
func (p *Provider) LoadRoutes() (err gperr.Error) {
func (p *Provider) LoadRoutes() (err error) {
p.routes, err = p.loadRoutes()
return err
}
@@ -188,7 +188,7 @@ func (p *Provider) GetRoute(alias string) (types.Route, bool) {
return r.Impl(), true
}
func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) {
func (p *Provider) loadRoutes() (routes route.Routes, err error) {
routes, err = p.loadRoutesImpl()
if err != nil && len(routes) == 0 {
return route.Routes{}, err
@@ -201,7 +201,7 @@ func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) {
r.Alias = alias
r.SetProvider(p)
if err := r.Validate(); err != nil {
errs.Add(err.Subject(alias))
errs.AddSubject(err, alias)
delete(routes, alias)
continue
}
@@ -210,11 +210,11 @@ func (p *Provider) loadRoutes() (routes route.Routes, err gperr.Error) {
return routes, errs.Error()
}
func (p *Provider) startRoute(parent task.Parent, r *route.Route) gperr.Error {
func (p *Provider) startRoute(parent task.Parent, r *route.Route) error {
err := r.Start(parent)
if err != nil {
p.lockDeleteRoute(r.Alias)
return err.Subject(r.Alias)
return gperr.PrependSubject(err, r.Alias)
}
p.lockAddRoute(r)