Documentation
¶
Overview ¶
Package pgfx is a thin, Fx-first layer over pgx/pgxpool for Postgres. A pgfx connection is a single *pgxpool.Pool built from a plain, serializable Config. Runtime dependencies (tracer, query metrics, pool hooks, an in-memory *tls.Config) are supplied through Option values, never through Config.
pgfx is meant to be wired with Uber Fx. Module is the default single connection and ModuleFor adds a replica or another shard; both consume a pgfx.Config the application supplies (typically via confmaker/confx) and manage the pool's lifecycle. pgfx does not read any config source itself, so it stays decoupled from confmaker. Multiple databases are simply multiple named connections. To build a pool without Fx, call Make with a Config you fill yourself.
Index ¶
- Variables
- func FetchRow[T any](ctx context.Context, q Querier, sql string, args ...any) (T, error)
- func FetchRows[T any](ctx context.Context, q Querier, sql string, args ...any) ([]T, error)
- func FetchValue[T any](ctx context.Context, q Querier, sql string, args ...any) (T, error)
- func FetchValues[T any](ctx context.Context, q Querier, sql string, args ...any) ([]T, error)
- func Make(ctx context.Context, cfg Config, opts ...Option) (*pgxpool.Pool, error)
- func ModuleFor(name string) fx.Option
- func QueryName(ctx context.Context) string
- func Tx(ctx context.Context, db TxBeginner, opts pgx.TxOptions, fn func(pgx.Tx) error) (err error)
- func WithQueryName(ctx context.Context, name string) context.Context
- type Config
- type Option
- func WithAfterConnect(fn func(context.Context, *pgx.Conn) error) Option
- func WithBeforeConnect(fn func(context.Context, *pgx.ConnConfig) error) Option
- func WithDefaultQueryExecMode(mode pgx.QueryExecMode) Option
- func WithQueryMetrics(fn QueryMetricFunc) Option
- func WithRuntimeParam(key, value string) Option
- func WithSQLInQueryMetrics(include bool) Option
- func WithStatementCacheCapacity(capacity int) Option
- func WithTLS(tlsConfig *tls.Config) Option
- func WithTracer(tracer pgx.QueryTracer) Option
- func WithTracing(opts ...otelpgx.Option) Option
- type PoolConfig
- type Querier
- type QueryMetric
- type QueryMetricFunc
- type TLSConfig
- type TimeoutConfig
- type TxBeginner
Constants ¶
This section is empty.
Variables ¶
var Module = fx.Module("pgfx", poolProvider(``))
Module is an Fx module for the default Postgres connection: it consumes an untagged pgfx.Config from the container and provides an untagged *pgxpool.Pool, so a repository just depends on *pgxpool.Pool - no tags, no wrappers.
The application supplies the Config explicitly - pgfx does not read any config source itself - typically with confmaker/confx:
fx.New(
confx.Module(),
confx.Provide[pgfx.Config]("postgres"),
pgfx.Module,
)
The pool is pinged on start (fail-fast on a dead database) and closed on stop, and takes an optional trace.TracerProvider and QueryMetricFunc from the container.
Functions ¶
func FetchRow ¶
FetchRow runs the query on q and decodes exactly one struct row into T. It returns sql.ErrNoRows when the query yields no rows, and pgx.ErrTooManyRows when it yields more than one. For a scalar result use FetchValue.
func FetchRows ¶
FetchRows runs the query on q and decodes every row into a struct T. Columns map to struct fields by the `db:"..."` tag (falling back to the field name). For a single-column (scalar) result use FetchValues.
func FetchValue ¶
FetchValue runs the query on q and decodes exactly one single-column row into a scalar T. It is the helper for count(*), INSERT ... RETURNING id and similar. It returns sql.ErrNoRows when the query yields no rows, and pgx.ErrTooManyRows when it yields more than one. For struct rows use FetchRow.
func FetchValues ¶
FetchValues runs the query on q and decodes a single-column result into a slice of scalar T (int64, string, uuid.UUID, ...). For struct rows use FetchRows.
func Make ¶
Make validates cfg and opens a connection pool for it, applying the runtime opts. The caller owns the returned pool and must Close it (the fx module does this via lifecycle).
func ModuleFor ¶
ModuleFor is an Fx module for a named connection - a replica or another shard. It consumes a pgfx.Config tagged name:"<name>" and provides a *pgxpool.Pool tagged the same; a consumer selects it with fx.ParamTags. The application supplies the tagged Config explicitly (typically confmaker/confx's Provide).
func Tx ¶
func Tx( ctx context.Context, db TxBeginner, opts pgx.TxOptions, fn func(pgx.Tx) error, ) (err error)
Tx runs fn inside a transaction begun on db and commits it, or rolls back on error or panic. The transaction is passed explicitly to fn (no ambient transaction via context): because pgx.Tx satisfies Querier, FetchRow/FetchRows work on it unchanged.
opts selects the isolation level (e.g. pgx.TxOptions{IsoLevel: pgx.Serializable}).
Tx does not retry serialization failures (SQLSTATE 40001) and does not nest: calling Tx from within fn opens a second top-level transaction on a different connection, not a savepoint. Handle both concerns at the call site if needed.
Types ¶
type Config ¶
type Config struct {
// Host is the endpoint as "host" or "host:port". A port in the string wins;
// when omitted, 5432 applies. IPv6 with a port must be bracketed
// ("[::1]:5433").
Host string `env:"HOST,notEmpty"`
// Database is the PostgreSQL database name.
Database string `env:"DATABASE,notEmpty"`
// User is the PostgreSQL role. When empty, libpq selects its default.
User string `env:"USER"`
// Password is read from the environment only. When empty, libpq may use
// PGPASSWORD or .pgpass.
Password secret.Secret `env:"PASSWORD"`
// AppName is reported as application_name in pg_stat_activity.
AppName string `env:"APP_NAME"`
// TLS configures libpq transport security.
TLS TLSConfig `envPrefix:"TLS_"`
// Pool configures pgxpool sizing and connection lifetimes.
Pool PoolConfig `envPrefix:"POOL_"`
// Timeouts configures connection timeouts.
Timeouts TimeoutConfig `envPrefix:"TIMEOUTS_"`
}
Config is the serializable configuration of a single Postgres connection. It carries only plain, serializable values - no tracer, hooks, or other runtime dependencies (those are passed to Make as Option values).
The `env` tags let a loader fill it from the environment (see confmaker/confx). They are inert strings, so the Config type itself depends only on the standard-library-only github.com/uchaloop/secret/v2 module.
Host and Database must be supplied by the deployment. User and Password are optional: when empty they fall back to libpq's defaults (PGUSER / the OS user, and PGPASSWORD / .pgpass).
type Option ¶
type Option func(*options)
Option configures the runtime behaviour of a connection built by Make.
func WithAfterConnect ¶
WithAfterConnect installs pgxpool.Config.AfterConnect - the usual place for custom pgx type registration.
func WithBeforeConnect ¶
WithBeforeConnect installs pgxpool.Config.BeforeConnect - invoked before establishing each new connection (e.g. to rotate a password).
func WithDefaultQueryExecMode ¶
func WithDefaultQueryExecMode(mode pgx.QueryExecMode) Option
WithDefaultQueryExecMode sets the default pgx.QueryExecMode.
func WithQueryMetrics ¶
func WithQueryMetrics(fn QueryMetricFunc) Option
WithQueryMetrics installs a second pgx.QueryTracer that reports a QueryMetric for every query (composed with the span tracer). nil disables it.
func WithRuntimeParam ¶
WithRuntimeParam adds a single pgx.ConnConfig.RuntimeParams value (SET key = value on connect).
func WithSQLInQueryMetrics ¶
WithSQLInQueryMetrics includes the raw SQL in QueryMetric.SQL (default off). Enable only when statements are safe to expose.
func WithStatementCacheCapacity ¶
WithStatementCacheCapacity sets the statement-cache size per connection.
func WithTLS ¶
WithTLS sets the connection's *tls.Config directly, overriding whatever the file-based Config.TLS produced (sslmode and the cert/key/root-cert paths). Use it when certificates are not files on disk - loaded from a secret manager, held in memory, or rotated at runtime: the application builds the *tls.Config and passes it here. It also removes libpq TLS/plaintext fallbacks so every connection attempt uses exactly this configuration. A nil value disables TLS.
func WithTracer ¶
func WithTracer(tracer pgx.QueryTracer) Option
WithTracer adds a custom pgx.QueryTracer (for example an AWS X-Ray tracer). It composes with WithTracing and WithQueryMetrics rather than replacing them.
type PoolConfig ¶
type PoolConfig struct {
// MaxConns is the maximum pool size.
MaxConns int32 `env:"MAX_CONNS"`
// MinConns is the minimum number of connections maintained by the pool.
MinConns int32 `env:"MIN_CONNS"`
// MinIdleConns is the minimum number of idle connections maintained by the
// pool.
MinIdleConns int32 `env:"MIN_IDLE_CONNS"`
// MaxConnLifetime is the maximum lifetime of a connection.
MaxConnLifetime time.Duration `env:"MAX_CONN_LIFETIME"`
// MaxConnLifetimeJitter randomizes connection expiry to avoid synchronized
// reconnects.
MaxConnLifetimeJitter time.Duration `env:"MAX_CONN_LIFETIME_JITTER"`
// MaxConnIdleTime is the maximum time a connection may remain idle.
MaxConnIdleTime time.Duration `env:"MAX_CONN_IDLE_TIME"`
// HealthPeriod controls how often pgxpool checks idle connections.
HealthPeriod time.Duration `env:"HEALTH_PERIOD"`
}
PoolConfig holds pgxpool sizing and connection-lifecycle settings. Zero values leave the pgxpool defaults in place.
type Querier ¶
Querier is the minimal query surface the generic fetch helpers need. It is satisfied by *pgxpool.Pool, *pgx.Conn and pgx.Tx alike, so the helpers run unchanged both directly on a pool and inside a transaction.
type QueryMetric ¶
type QueryMetric struct {
// Name is the bounded label from WithQueryName ("" if unset) - use it as the
// metric label, never SQL (raw statements have unbounded cardinality).
Name string
// SQL is the raw statement when explicitly enabled with WithSQLInQueryMetrics;
// otherwise it is empty. Do NOT use it as a metric label, and scrub it before
// recording.
SQL string
// Duration is the wall time from query start to end.
Duration time.Duration
// RowsAffected is the number of rows affected or returned as reported by pgx.
RowsAffected int64
// Err is non-nil when the query failed.
Err error
}
QueryMetric is one observed query, passed to a QueryMetricFunc.
type QueryMetricFunc ¶
type QueryMetricFunc func(QueryMetric)
QueryMetricFunc receives one QueryMetric per query. It runs on the query hot path, so it must be cheap and non-blocking. The package ships no metrics dependency - this callback is the seam where you plug one in.
type TLSConfig ¶
type TLSConfig struct {
// Mode is the libpq sslmode (disable/allow/prefer/require/verify-ca/
// verify-full). Empty leaves the libpq default ("prefer").
//
// SECURITY: "prefer"/"allow" fall back to unencrypted and never verify the
// server certificate; "require" encrypts but still does not verify it. Use
// "verify-full" with RootCert for MITM protection.
Mode string `env:"MODE"`
// Cert is the path to the client certificate.
Cert string `env:"CERT"`
// Key is the path to the client private key.
Key string `env:"KEY"`
// RootCert is the path to the trusted root certificate.
RootCert string `env:"ROOT_CERT"`
// ServerName overrides the TLS server name used for verification.
ServerName string `env:"SERVER_NAME"`
}
TLSConfig holds the libpq TLS settings.
type TimeoutConfig ¶
type TimeoutConfig struct {
// Connect bounds establishing a single connection. Zero leaves the pgx
// default.
Connect time.Duration `env:"CONNECT"`
}
TimeoutConfig holds connection timeouts.
type TxBeginner ¶
TxBeginner starts transactions. It is satisfied by *pgxpool.Pool and *pgx.Conn, so Tx runs on a pool or a single connection alike - the transaction-level counterpart of Querier for the fetch helpers.