Files
agentic-coding-workflow/internal/infra/db/postgres.go
T

57 lines
1.8 KiB
Go

package db
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
// 默认连接池配置:10–50 用户私部署量级够用;超出后再按实际负载调整。
const (
defaultMaxConns = 20
defaultMinConns = 2
defaultMaxConnLifetime = time.Hour // 单连接最大寿命,到点后回收重建
defaultMaxConnLifetimeJitter = defaultMaxConnLifetime / 10 // 在寿命基础上叠加 0~6 分钟随机抖动,防同步重建 storm
defaultPingTimeout = 5 * time.Second
defaultHealthTimeout = time.Second
)
// Pool 是 pgxpool.Pool 的类型别名,外部代码可直接以 db.Pool 表达连接池类型,
// 同时保留 pgx 原生方法(Acquire/Exec/Query/...)。
type Pool = pgxpool.Pool
// NewPool 根据 dsn 构建 Postgres 连接池,并在返回前用 5s 超时的 Ping 做健康验证。
// 失败时关闭已创建的池并返回错误,避免泄露资源。
func NewPool(ctx context.Context, dsn string) (*Pool, error) {
cfg, err := pgxpool.ParseConfig(dsn)
if err != nil {
return nil, fmt.Errorf("parse dsn: %w", err)
}
cfg.MaxConns = defaultMaxConns
cfg.MinConns = defaultMinConns
cfg.MaxConnLifetime = defaultMaxConnLifetime
cfg.MaxConnLifetimeJitter = defaultMaxConnLifetimeJitter
pool, err := pgxpool.NewWithConfig(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("new pool: %w", err)
}
pingCtx, cancel := context.WithTimeout(ctx, defaultPingTimeout)
defer cancel()
if err := pool.Ping(pingCtx); err != nil {
pool.Close()
return nil, fmt.Errorf("ping: %w", err)
}
return pool, nil
}
// HealthCheck 用 1s 超时探测数据库连通性,供 healthz/readyz 等探针调用。
func HealthCheck(ctx context.Context, pool *Pool) error {
c, cancel := context.WithTimeout(ctx, defaultHealthTimeout)
defer cancel()
return pool.Ping(c)
}