package db import ( "context" "database/sql" "fmt" "os" "strconv" "time" _ "github.com/jackc/pgx/v5/stdlib" ) func OpenDB(ctx context.Context) (*sql.DB, error) { dsn := os.Getenv("DATABASE_URL") if dsn == "" { host := getenv("DB_HOST", "localhost") port := getenv("DB_PORT", "5432") user := getenv("DB_USER", "party") pass := getenv("DB_PASS", "secret") name := getenv("DB_NAME", "partydb") ssl := getenv("DB_SSLMODE", "disable") dsn = fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=%s", user, pass, host, port, name, ssl) } db, err := sql.Open("pgx", dsn) if err != nil { return nil, err } // Connection pool tuning if v := os.Getenv("DB_MAX_OPEN_CONNS"); v != "" { if n, err := strconv.Atoi(v); err == nil { db.SetMaxOpenConns(n) } } else { db.SetMaxOpenConns(25) } if v := os.Getenv("DB_MAX_IDLE_CONNS"); v != "" { if n, err := strconv.Atoi(v); err == nil { db.SetMaxIdleConns(n) } } else { db.SetMaxIdleConns(25) } if v := os.Getenv("DB_CONN_MAX_LIFETIME"); v != "" { if d, err := time.ParseDuration(v); err == nil { db.SetConnMaxLifetime(d) } } else { db.SetConnMaxLifetime(30 * time.Minute) } ctxPing, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() if err := db.PingContext(ctxPing); err != nil { db.Close() return nil, err } return db, nil } func getenv(key, def string) string { if v := os.Getenv(key); v != "" { return v } return def }