From be181f82453427041d760c1bb14b74166ebb8a34 Mon Sep 17 00:00:00 2001 From: bvandeusen Date: Sat, 18 Apr 2026 21:19:39 +0000 Subject: [PATCH] feat(skel): add cmd/minstrel entrypoint Parses --config / SMARTMUSIC_CONFIG, loads YAML config with env overlay, initializes slog, starts the chi HTTP server, and shuts down cleanly on SIGINT/SIGTERM. --- cmd/minstrel/main.go | 81 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 cmd/minstrel/main.go diff --git a/cmd/minstrel/main.go b/cmd/minstrel/main.go new file mode 100644 index 00000000..4de77cc6 --- /dev/null +++ b/cmd/minstrel/main.go @@ -0,0 +1,81 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "git.fabledsword.com/bvandeusen/minstrel/internal/config" + "git.fabledsword.com/bvandeusen/minstrel/internal/logging" + "git.fabledsword.com/bvandeusen/minstrel/internal/server" +) + +func main() { + if err := run(); err != nil { + fmt.Fprintf(os.Stderr, "minstrel: %v\n", err) + os.Exit(1) + } +} + +func run() error { + configPath := flag.String("config", os.Getenv("SMARTMUSIC_CONFIG"), "path to YAML config file") + flag.Parse() + + cfg, err := config.Load(*configPath) + if err != nil { + return fmt.Errorf("load config: %w", err) + } + + logger, err := logging.New(os.Stdout, cfg.Log.Level, cfg.Log.Format) + if err != nil { + return fmt.Errorf("init logger: %w", err) + } + + logger.Info("minstrel starting", + "address", cfg.Server.Address, + "log_level", cfg.Log.Level, + "log_format", cfg.Log.Format, + ) + + srv := server.New(logger) + httpServer := &http.Server{ + Addr: cfg.Server.Address, + Handler: srv.Router(), + ReadHeaderTimeout: 10 * time.Second, + } + + ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer stop() + + errCh := make(chan error, 1) + go func() { + logger.Info("listening", "address", cfg.Server.Address) + if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + errCh <- err + } + close(errCh) + }() + + select { + case <-ctx.Done(): + logger.Info("shutdown signal received") + case err := <-errCh: + if err != nil { + return fmt.Errorf("server: %w", err) + } + } + + shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err := httpServer.Shutdown(shutdownCtx); err != nil { + return fmt.Errorf("shutdown: %w", err) + } + logger.Info("minstrel stopped") + return nil +}