trepa/cmd/api/main.go
2025-03-11 21:42:36 +00:00

111 lines
2.1 KiB
Go

package main
import (
"context"
_ "embed"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"gitea.qpismont.fr/qpismont/trepa/internal/accounts/api"
"gitea.qpismont.fr/qpismont/trepa/internal/core"
"github.com/jmoiron/sqlx"
)
//go:embed ascii
var ascii string
func main() {
fmt.Println(ascii)
core.LoadEnvVars(".env")
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()
api.BindRoutes(router, db)
return router
}