package main import ( "context" "errors" "flag" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "go-htmx-chat/internal/chat" "go-htmx-chat/internal/store" "go-htmx-chat/internal/web" ) func main() { addr := flag.String("addr", ":8080", "HTTP listen address") dbPath := flag.String("db", "data/chat.json", "JSON data file path") flag.Parse() logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) st, err := store.Open(*dbPath) if err != nil { logger.Error("open store", "error", err) os.Exit(1) } defer st.Close() authCfg, err := web.AuthConfigFromEnv(logger) if err != nil { logger.Error("auth config", "error", err) os.Exit(1) } srv, err := web.NewServer(st, chat.NewHub(), logger, authCfg) if err != nil { logger.Error("new server", "error", err) os.Exit(1) } httpServer := &http.Server{ Addr: *addr, Handler: srv.Routes(), ReadHeaderTimeout: 5 * time.Second, } go func() { logger.Info("listening", "addr", *addr) if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { logger.Error("listen", "error", err) os.Exit(1) } }() stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt, syscall.SIGTERM) <-stop ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _ = httpServer.Shutdown(ctx) logger.Info("server stopped") }