From 18b307bca19e65292a0a0cc5b51daf3ede7870d0 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Fri, 26 Dec 2025 10:39:09 -0600 Subject: [PATCH] control flow of router running with better context handling and logging in cmd --- cmd/showbridge/main.go | 108 +++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/cmd/showbridge/main.go b/cmd/showbridge/main.go index e2eb34c..2b00f6f 100644 --- a/cmd/showbridge/main.go +++ b/cmd/showbridge/main.go @@ -6,6 +6,7 @@ import ( "log/slog" "os" "os/signal" + "sync" "github.com/jwetzell/showbridge-go" "github.com/jwetzell/showbridge-go/internal/config" @@ -39,54 +40,10 @@ func main() { Usage: "log using JSON", }, }, - Action: func(ctx context.Context, c *cli.Command) error { - configPath := c.String("config") - if configPath == "" { - return errors.New("config value cannot be empty") - } - - config, err := readConfig(configPath) - if err != nil { - return err - } - - logLevel := slog.LevelInfo - - if c.Bool("debug") { - logLevel = slog.LevelDebug - } - - logHandlerOptions := &slog.HandlerOptions{ - Level: logLevel, - } - - logOutput := os.Stderr - - var logHandler slog.Handler = slog.NewTextHandler(logOutput, logHandlerOptions) - - if c.Bool("json") { - logHandler = slog.NewJSONHandler(logOutput, logHandlerOptions) - } - - logger := slog.New(logHandler) - - slog.SetDefault(logger) - - router, moduleErrors, routeErrors := showbridge.NewRouter(ctx, config) - - for _, moduleError := range moduleErrors { - logger.Error("problem initializing module", "index", moduleError.Index, "error", moduleError.Error) - } - - for _, routeError := range routeErrors { - logger.Error("problem initializing route", "index", routeError.Index, "error", routeError.Error) - } - router.Run() - return nil - }, + Action: run, } - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Interrupt) + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) defer cancel() err := cmd.Run(ctx, os.Args) @@ -112,3 +69,62 @@ func readConfig(configPath string) (config.Config, error) { return cfg, nil } + +func run(ctx context.Context, c *cli.Command) error { + configPath := c.String("config") + if configPath == "" { + return errors.New("config value cannot be empty") + } + + config, err := readConfig(configPath) + if err != nil { + return err + } + + logLevel := slog.LevelInfo + + if c.Bool("debug") { + logLevel = slog.LevelDebug + } + + logHandlerOptions := &slog.HandlerOptions{ + Level: logLevel, + } + + logOutput := os.Stderr + + var logHandler slog.Handler = slog.NewTextHandler(logOutput, logHandlerOptions) + + if c.Bool("json") { + logHandler = slog.NewJSONHandler(logOutput, logHandlerOptions) + } + + slog.SetDefault(slog.New(logHandler)) + + commandLogger := slog.Default().With("component", "cmd") + + routerContext, routerCancel := context.WithCancel(context.Background()) + + router, moduleErrors, routeErrors := showbridge.NewRouter(routerContext, config) + + for _, moduleError := range moduleErrors { + commandLogger.Error("problem initializing module", "index", moduleError.Index, "error", moduleError.Error) + } + + for _, routeError := range routeErrors { + commandLogger.Error("problem initializing route", "index", routeError.Index, "error", routeError.Error) + } + + routerRunner := sync.WaitGroup{} + + routerRunner.Go(func() { + router.Run() + }) + + <-ctx.Done() + commandLogger.Debug("shutting down router") + routerCancel() + commandLogger.Debug("waiting for router to exit") + routerRunner.Wait() + return nil +}