From ef3aa146b561d67bd46080620fefbd4ef63574b2 Mon Sep 17 00:00:00 2001 From: yusing Date: Mon, 26 Jan 2026 23:51:18 +0800 Subject: [PATCH] refactor(config): simplify route provider loading with improved error handling Streamlined the `loadRouteProviders()` function by: - Replacing channel-based concurrency with a simpler sequential registration pattern after agent initialization - Using `gperr.NewGroup` and `gperr.NewBuilder` for more idiomatic error handling - Adding mutex protection for concurrent result building - Removing the `storeProvider` helper method --- internal/config/state.go | 83 ++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/internal/config/state.go b/internal/config/state.go index e06bd901..57202905 100644 --- a/internal/config/state.go +++ b/internal/config/state.go @@ -317,67 +317,50 @@ func (state *state) initProxmox() error { return errs.Wait().Error() } -func (state *state) storeProvider(p types.RouteProvider) { - state.providers.Store(p.String(), p) -} - func (state *state) loadRouteProviders() error { - providers := &state.Providers + providers := state.Providers errs := gperr.NewGroup("route provider errors") - results := gperr.NewGroup("loaded route providers") agentpool.RemoveAll() - numProviders := len(providers.Agents) + len(providers.Files) + len(providers.Docker) - providersCh := make(chan types.RouteProvider, numProviders) - - // start providers concurrently - var providersConsumer sync.WaitGroup - providersConsumer.Go(func() { - for p := range providersCh { - if actual, loaded := state.providers.LoadOrStore(p.String(), p); loaded { - errs.Add(gperr.Errorf("provider %s already exists, first: %s, second: %s", p.String(), actual.GetType(), p.GetType())) - continue - } - state.storeProvider(p) + registerProvider := func(p types.RouteProvider) { + if actual, loaded := state.providers.LoadOrStore(p.String(), p); loaded { + errs.Addf("provider %s already exists, first: %s, second: %s", p.String(), actual.GetType(), p.GetType()) } - }) + } - var providersProducer sync.WaitGroup + agentErrs := gperr.NewGroup("agent init errors") for _, a := range providers.Agents { - providersProducer.Go(func() { + agentErrs.Go(func() error { if err := a.Init(state.task.Context()); err != nil { - errs.Add(gperr.PrependSubject(a.String(), err)) - return + return gperr.PrependSubject(a.String(), err) } agentpool.Add(a) - p := route.NewAgentProvider(a) - providersCh <- p + return nil }) } + if err := agentErrs.Wait().Error(); err != nil { + errs.Add(err) + } + + for _, a := range providers.Agents { + registerProvider(route.NewAgentProvider(a)) + } + for _, filename := range providers.Files { - providersProducer.Go(func() { - p, err := route.NewFileProvider(filename) - if err != nil { - errs.Add(gperr.PrependSubject(filename, err)) - } else { - providersCh <- p - } - }) + p, err := route.NewFileProvider(filename) + if err != nil { + errs.Add(gperr.PrependSubject(filename, err)) + return err + } + registerProvider(p) } for name, dockerCfg := range providers.Docker { - providersProducer.Go(func() { - providersCh <- route.NewDockerProvider(name, dockerCfg) - }) + registerProvider(route.NewDockerProvider(name, dockerCfg)) } - providersProducer.Wait() - - close(providersCh) - providersConsumer.Wait() - lenLongestName := 0 for k := range state.providers.Range { if len(k) > lenLongestName { @@ -386,18 +369,26 @@ func (state *state) loadRouteProviders() error { } // load routes concurrently - var providersLoader sync.WaitGroup + loadErrs := gperr.NewGroup("route load errors") + + results := gperr.NewBuilder("loaded route providers") + resultsMu := sync.Mutex{} for _, p := range state.providers.Range { - providersLoader.Go(func() { + loadErrs.Go(func() error { if err := p.LoadRoutes(); err != nil { - errs.Add(err.Subject(p.String())) + return err.Subject(p.String()) } + resultsMu.Lock() results.Addf("%-"+strconv.Itoa(lenLongestName)+"s %d routes", p.String(), p.NumRoutes()) + resultsMu.Unlock() + return nil }) } - providersLoader.Wait() + if err := loadErrs.Wait().Error(); err != nil { + errs.Add(err) + } - state.tmpLog.Info().Msg(results.Wait().String()) + state.tmpLog.Info().Msg(results.String()) state.printRoutesByProvider(lenLongestName) state.printState() return errs.Wait().Error()