package dbpool import ( "context" "fmt" "time" "github.com/jackc/pgx/v5/pgxpool" ) type PoolConfig struct { MaxOpenConns int MinIdleConns int MaxConnLifetime time.Duration MaxConnIdleTime time.Duration HealthCheckPeriod time.Duration ConnectionAcquireWait time.Duration } func NewPostgresPool(ctx context.Context, databaseURL string, pool PoolConfig) (*pgxpool.Pool, error) { cfg, err := pgxpool.ParseConfig(databaseURL) if err != nil { return nil, fmt.Errorf("parse postgres pool config: %w", err) } if pool.MaxOpenConns <= 0 { pool.MaxOpenConns = 25 } if pool.MinIdleConns < 0 { pool.MinIdleConns = 0 } if pool.MinIdleConns > pool.MaxOpenConns { pool.MinIdleConns = pool.MaxOpenConns } if pool.MaxConnLifetime <= 0 { pool.MaxConnLifetime = 30 * time.Minute } if pool.MaxConnIdleTime <= 0 { pool.MaxConnIdleTime = 5 * time.Minute } if pool.HealthCheckPeriod <= 0 { pool.HealthCheckPeriod = time.Minute } if pool.ConnectionAcquireWait <= 0 { pool.ConnectionAcquireWait = 10 * time.Second } cfg.MaxConns = int32(pool.MaxOpenConns) cfg.MinConns = int32(pool.MinIdleConns) cfg.MaxConnLifetime = pool.MaxConnLifetime cfg.MaxConnIdleTime = pool.MaxConnIdleTime cfg.HealthCheckPeriod = pool.HealthCheckPeriod pingCtx, cancel := context.WithTimeout(ctx, pool.ConnectionAcquireWait) defer cancel() poolConn, err := pgxpool.NewWithConfig(ctx, cfg) if err != nil { return nil, fmt.Errorf("open postgres pool: %w", err) } if err := poolConn.Ping(pingCtx); err != nil { poolConn.Close() return nil, fmt.Errorf("ping postgres: %w", err) } return poolConn, nil }