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 +}