package main import ( "context" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "github.com/jacek/pamietnik/backend/internal/api" "github.com/jacek/pamietnik/backend/internal/auth" "github.com/jacek/pamietnik/backend/internal/db" ) func main() { logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) slog.SetDefault(logger) dsn := getenv("DATABASE_URL", "postgres://pamietnik:pamietnik@localhost:5432/pamietnik?sslmode=disable") addr := getenv("LISTEN_ADDR", ":8080") uploadDir := getenv("UPLOAD_DIR", "./uploads") ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() pool, err := db.NewPool(ctx, dsn) if err != nil { slog.Error("connect db", "err", err) os.Exit(1) } defer pool.Close() slog.Info("database connected") if err := db.InitSchema(ctx, pool); err != nil { slog.Error("init schema", "err", err) os.Exit(1) } slog.Info("schema ready") if err := os.MkdirAll(uploadDir, 0o755); err != nil { slog.Error("create upload dir", "err", err) os.Exit(1) } authStore := auth.NewStore(pool) tpStore := db.NewTrackpointStore(pool) stopStore := db.NewStopStore(pool) suggStore := db.NewSuggestionStore(pool) journalStore := db.NewJournalStore(pool) router := api.NewRouter(authStore, tpStore, stopStore, suggStore, journalStore, uploadDir) srv := &http.Server{ Addr: addr, Handler: router, ReadTimeout: 15 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 60 * time.Second, } go func() { slog.Info("server starting", "addr", addr) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error("server error", "err", err) cancel() } }() <-ctx.Done() slog.Info("shutting down") shutCtx, shutCancel := context.WithTimeout(context.Background(), 10*time.Second) defer shutCancel() if err := srv.Shutdown(shutCtx); err != nil { slog.Error("shutdown error", "err", err) } slog.Info("server stopped") } func getenv(key, fallback string) string { if v := os.Getenv(key); v != "" { return v } return fallback }