package main import ( "context" _ "embed" "fmt" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "gitea.qpismont.fr/qpismont/trepa/internal/accounts" "gitea.qpismont.fr/qpismont/trepa/internal/core" "github.com/jmoiron/sqlx" ) //go:embed ascii var ascii string func main() { fmt.Println(ascii) core.LoadEnvVars() db := setupDB() router := setupRouter(db) server := &http.Server{ Addr: ":3000", Handler: router, } shutdownChan := make(chan os.Signal, 1) done := make(chan bool, 1) signal.Notify(shutdownChan, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL) go func() { sig := <-shutdownChan slog.Info("Shutdown signal received", "signal", sig) timeoutCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() slog.Info("Shutting down HTTP server") if err := server.Shutdown(timeoutCtx); err != nil { slog.Error("HTTP server forced to shutdown", "error", err) } slog.Info("Closing database connection") if err := db.Close(); err != nil { slog.Error("Error closing database connection", "error", err) } slog.Info("Shutting down application") select { case <-timeoutCtx.Done(): slog.Error("Shutdown timed out, forcing exit") done <- false default: slog.Info("Graceful shutdown completed") done <- true } }() if err := server.ListenAndServe(); err != nil { if err != http.ErrServerClosed { slog.Error("HTTP server failed", "error", err) os.Exit(1) } } if success := <-done; !success { os.Exit(1) } os.Exit(0) } func setupDB() *sqlx.DB { dbURL := core.ComputeDBURL( core.MustGetEnvVar("DB_HOST"), core.MustGetEnvVar("DB_PORT"), core.MustGetEnvVar("DB_USER"), core.MustGetEnvVar("DB_PASSWORD"), core.MustGetEnvVar("DB_NAME"), ) slog.Info("Connecting to database", "url", dbURL) db, err := core.SetupDB(dbURL) if err != nil { slog.Error("Failed to connect to database", "error", err) panic(err) } slog.Info("Connected to database") return db } func setupRouter(db *sqlx.DB) *core.ServerMux { router := core.NewServerMux() accounts.BindRoutes(router, db) return router }