package dbx import ( "context" "sync/atomic" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgxpool" ) // Node wraps a pgxpool.Pool with health state and a human-readable name. type Node struct { name string pool *pgxpool.Pool healthy atomic.Bool } // newNode creates a Node from an existing pool. func newNode(name string, pool *pgxpool.Pool) *Node { n := &Node{ name: name, pool: pool, } n.healthy.Store(true) return n } // connectNode parses the NodeConfig, creates a pgxpool.Pool, and returns a Node. func connectNode(ctx context.Context, cfg NodeConfig) (*Node, error) { poolCfg, err := pgxpool.ParseConfig(cfg.DSN) if err != nil { return nil, err } applyPoolConfig(poolCfg, cfg.Pool) if cfg.Tracer != nil { poolCfg.ConnConfig.Tracer = cfg.Tracer } pool, err := pgxpool.NewWithConfig(ctx, poolCfg) if err != nil { return nil, err } return newNode(cfg.Name, pool), nil } func applyPoolConfig(dst *pgxpool.Config, src PoolConfig) { if src.MaxConns > 0 { dst.MaxConns = src.MaxConns } if src.MinConns > 0 { dst.MinConns = src.MinConns } if src.MaxConnLifetime > 0 { dst.MaxConnLifetime = src.MaxConnLifetime } if src.MaxConnIdleTime > 0 { dst.MaxConnIdleTime = src.MaxConnIdleTime } if src.HealthCheckPeriod > 0 { dst.HealthCheckPeriod = src.HealthCheckPeriod } } // Name returns the node's human-readable name. func (n *Node) Name() string { return n.name } // IsHealthy reports whether the node is considered healthy. func (n *Node) IsHealthy() bool { return n.healthy.Load() } // Pool returns the underlying pgxpool.Pool. func (n *Node) Pool() *pgxpool.Pool { return n.pool } // --- DB interface implementation --- func (n *Node) Exec(ctx context.Context, sql string, args ...any) (pgconn.CommandTag, error) { return n.pool.Exec(ctx, sql, args...) } func (n *Node) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error) { return n.pool.Query(ctx, sql, args...) } func (n *Node) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row { return n.pool.QueryRow(ctx, sql, args...) } func (n *Node) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { return n.pool.SendBatch(ctx, b) } func (n *Node) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error) { return n.pool.CopyFrom(ctx, tableName, columnNames, rowSrc) } func (n *Node) Begin(ctx context.Context) (pgx.Tx, error) { return n.pool.Begin(ctx) } func (n *Node) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, error) { return n.pool.BeginTx(ctx, txOptions) } func (n *Node) Ping(ctx context.Context) error { return n.pool.Ping(ctx) } func (n *Node) Close() { n.pool.Close() } // Compile-time check that *Node implements DB. var _ DB = (*Node)(nil)