package main import ( "me-fit/handler" "me-fit/types" "me-fit/utils" "os" "context" "database/sql" "log" "log/slog" "net/http" "os/signal" "sync" "syscall" "time" "github.com/joho/godotenv" _ "github.com/mattn/go-sqlite3" "github.com/prometheus/client_golang/prometheus/promhttp" ) func main() { err := godotenv.Load() if err != nil { log.Fatal("Error loading .env file") } db, err := sql.Open("sqlite3", "./data.db") if err != nil { log.Fatal("Could not open Database data.db: ", err) } defer db.Close() run(context.Background(), db, os.Getenv) } func run(ctx context.Context, db *sql.DB, env func(string) string) { ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM) defer cancel() slog.Info("Starting server...") // init server settings serverSettings := types.NewServerSettingsFromEnv(env) // init db err := utils.RunMigrations(db, "") if err != nil { slog.Error("Could not run migrations: " + err.Error()) os.Exit(1) } // init servers var prometheusServer *http.Server if serverSettings.PrometheusEnabled { prometheusServer := &http.Server{ Addr: ":8081", Handler: promhttp.Handler(), } go startServer(prometheusServer) } httpServer := &http.Server{ Addr: ":" + serverSettings.Port, Handler: handler.GetHandler(db, serverSettings), } go startServer(httpServer) // graceful shutdown var wg sync.WaitGroup wg.Add(2) go shutdownServer(httpServer, ctx, &wg) go shutdownServer(prometheusServer, ctx, &wg) wg.Wait() } func startServer(s *http.Server) { slog.Info("Starting server on " + s.Addr) if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error("error listening and serving: " + err.Error()) } } func shutdownServer(s *http.Server, ctx context.Context, wg *sync.WaitGroup) { defer wg.Done() if s == nil { return } <-ctx.Done() shutdownCtx := context.Background() shutdownCtx, cancel := context.WithTimeout(shutdownCtx, 10*time.Second) defer cancel() if err := s.Shutdown(shutdownCtx); err != nil { slog.Error("error shutting down http server: " + err.Error()) } else { slog.Info("Gracefully stopped http server on " + s.Addr) } }