package postgres import ( "context" "fmt" "time" "github.com/jackc/pgx/v5/pgxpool" ) // PoolConfig holds the configuration for the database connection pool. type PoolConfig struct { MaxConns int MinConns int MaxConnLifetime time.Duration MaxConnIdleTime time.Duration HealthCheckPeriod time.Duration } // DefaultPoolConfig returns a reasonable default pool configuration. func DefaultPoolConfig() *PoolConfig { return &PoolConfig{ MaxConns: 10, MinConns: 2, MaxConnLifetime: time.Hour, MaxConnIdleTime: 30 * time.Minute, HealthCheckPeriod: time.Minute, } } // NewPool creates a new database connection pool. If poolConfig is nil, // DefaultPoolConfig() is used. func NewPool(ctx context.Context, config *Config, poolConfig *PoolConfig) (*pgxpool.Pool, error) { if poolConfig == nil { poolConfig = DefaultPoolConfig() } pgxConfig, err := pgxpool.ParseConfig(config.DSN()) if err != nil { return nil, fmt.Errorf("failed to parse pool config: %w", err) } pgxConfig.MaxConns = int32(poolConfig.MaxConns) pgxConfig.MinConns = int32(poolConfig.MinConns) pgxConfig.MaxConnLifetime = poolConfig.MaxConnLifetime pgxConfig.MaxConnIdleTime = poolConfig.MaxConnIdleTime pgxConfig.HealthCheckPeriod = poolConfig.HealthCheckPeriod pool, err := pgxpool.NewWithConfig(ctx, pgxConfig) if err != nil { return nil, fmt.Errorf("failed to create connection pool: %w", err) } if err := pool.Ping(ctx); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } return pool, nil } // ClosePool closes the database connection pool if it is non-nil. func ClosePool(pool *pgxpool.Pool) { if pool != nil { pool.Close() } }