postgres

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package postgres provides a pgxpool.Pool constructor with the operational defaults the source applications lacked: slow-query tracing (see slow_query_tracer.go), Prometheus pool metrics (see metrics.go), a hard startup failure instead of a silent no-op when TLS is required but the DSN does not enable it, and server-side statement/lock/idle-in-transaction timeouts applied on every new connection.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewPool

func NewPool(ctx context.Context, cfg Config, logger *slog.Logger) (*pgxpool.Pool, error)

NewPool creates and validates a *pgxpool.Pool from cfg. It fails fast (before returning a pool) if the DSN is invalid, if RequireTLS is true but the DSN does not enable TLS, or if the initial ping fails.

Types

type Config

type Config struct {
	// URL is the PostgreSQL connection string (DSN), e.g.
	// "postgres://user:pass@host:5432/db?sslmode=require".
	URL string

	MaxConns        int32
	MinConns        int32
	MaxConnLifetime time.Duration
	MaxConnIdleTime time.Duration
	ConnectTimeout  time.Duration

	// RequireTLS enforces a minimum TLS 1.2 connection. If true and the parsed
	// DSN does not enable TLS (e.g. sslmode=disable), NewPool fails fast with
	// an error instead of silently opening a plaintext connection. See
	// applyTLSConfig for the historical bug this fixes.
	RequireTLS bool

	// StatementTimeout caps how long a single SQL statement may run before
	// PostgreSQL cancels it (server-side `SET statement_timeout`). Protects
	// against a runaway query holding a connection (and any locks it took)
	// indefinitely. Zero uses defaultStatementTimeout (30s); a negative value
	// disables the timeout explicitly.
	StatementTimeout time.Duration

	// LockTimeout caps how long a statement will wait to acquire a row/table
	// lock before failing (server-side `SET lock_timeout`). Protects against a
	// request queuing behind a lock held by another slow transaction instead
	// of failing fast and letting the caller retry or surface an error. Zero
	// uses defaultLockTimeout (5s); a negative value disables it explicitly.
	LockTimeout time.Duration

	// IdleInTransactionSessionTimeout caps how long a connection may sit idle
	// while inside an open transaction (server-side
	// `SET idle_in_transaction_session_timeout`) before PostgreSQL kills the
	// session.
	//
	// This is the timeout that matters most of the three: it is the only
	// server-side backstop against a handler bug that begins a transaction,
	// then hangs (a stuck downstream call, a forgotten context deadline, a
	// panic recovered above the DB layer without rolling back) while still
	// holding the transaction's row locks. Without it, that one stuck request
	// can block every other request that needs the same rows — potentially
	// the whole pool, if MaxConns is small — until the process is restarted.
	// statement_timeout does not help here because no statement is running;
	// the connection is simply idle with an open transaction.
	//
	// Zero uses defaultIdleInTransactionSessionTimeout (60s); a negative value
	// disables it explicitly.
	IdleInTransactionSessionTimeout time.Duration

	// AfterConnect, if set, runs after this package's own per-connection setup
	// (TLS, timeouts, tracer) on every new physical connection. Use it for
	// consumer-specific per-connection work — for example, registering a
	// custom pgtype codec such as jackc/pgx-shopspring-decimal, the way
	// go-crucible's original constructor did inline. Returning an error here
	// fails that connection attempt.
	AfterConnect func(ctx context.Context, conn *pgx.Conn) error
}

Config configures NewPool. Adapters own their Config struct rather than reading a global application config, so this type carries only what a pgxpool.Pool needs — the consuming application decides how (env vars, a flags package, hardcoded test values, ...) to fill it in.

type PoolMetricsCollector

type PoolMetricsCollector struct {
	// contains filtered or unexported fields
}

PoolMetricsCollector exports pgxpool stats as Prometheus metrics.

Unlike a package-level prometheus.MustRegister, NewPoolMetricsCollector is safe to call more than once against the same Registerer: a prometheus.AlreadyRegisteredError is handled by reusing the already registered collector instead of panicking. This matters for a library — a consumer may build two pools (e.g. in a test that constructs a fresh app per test case) and must not have the second one panic the process.

Reusing the existing collector means a second NewPoolMetricsCollector call against the same Registerer returns the FIRST pool's collector, still bound to the first pool. If a consumer genuinely needs metrics for two distinct, simultaneously-live pools, register each with its own prometheus.Registerer (e.g. a dedicated prometheus.NewRegistry()) rather than sharing one.

func NewPoolMetricsCollector

func NewPoolMetricsCollector(pool *pgxpool.Pool, reg prometheus.Registerer) (*PoolMetricsCollector, error)

NewPoolMetricsCollector creates a collector for pool and registers it on reg. If reg is nil, prometheus.DefaultRegisterer is used.

func (*PoolMetricsCollector) Collect

func (c *PoolMetricsCollector) Collect(ch chan<- prometheus.Metric)

func (*PoolMetricsCollector) Describe

func (c *PoolMetricsCollector) Describe(ch chan<- *prometheus.Desc)

type SlowQueryTracer

type SlowQueryTracer struct {
	// contains filtered or unexported fields
}

SlowQueryTracer implements pgx.QueryTracer and logs queries that exceed the configured threshold.

func NewSlowQueryTracer

func NewSlowQueryTracer(logger *slog.Logger, threshold time.Duration) *SlowQueryTracer

NewSlowQueryTracer creates a tracer that logs queries slower than threshold.

func (*SlowQueryTracer) TraceQueryEnd

func (t *SlowQueryTracer) TraceQueryEnd(ctx context.Context, _ *pgx.Conn, data pgx.TraceQueryEndData)

func (*SlowQueryTracer) TraceQueryStart

func (t *SlowQueryTracer) TraceQueryStart(ctx context.Context, _ *pgx.Conn, data pgx.TraceQueryStartData) context.Context

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL