• v0.9.0 2baafa6a0c

    Rene Nochebuena released this 2026-03-19 07:18:59 -06:00 | 0 commits to main since this release

    v0.9.0

    code.nochebuena.dev/go/postgres

    Overview

    postgres is a pgx v5-native PostgreSQL client that integrates with the launcher lifecycle
    and health check systems. It manages a pgxpool connection pool, maps PostgreSQL errors to
    portable xerrors codes, and provides a UnitOfWork implementation that injects the active
    transaction into the context so repositories participate in transactions without explicit wiring.

    This is the first stable release. The API was designed through multiple architecture reviews
    and validated end-to-end via the todo-api proof-of-concept. It is versioned at v0.9.0 rather
    than v1.0.0 because the library has not yet been exercised in production across all edge cases;
    the pre-1.0 version preserves the option for minor API refinements without a major bump.

    What's Included

    • Executor interface: Exec, Query, QueryRow using pgx v5 native types
      (pgconn.CommandTag, pgx.Rows, pgx.Row)
    • Tx interface: extends Executor with Commit(ctx) / Rollback(ctx)
    • Client interface: GetExecutor(ctx), Begin(ctx), Ping(ctx), HandleError(err)
    • Component interface: composes launcher.Component, health.Checkable, and Client
    • New(logger, cfg) Component constructor; pool initialised in OnInit, not at construction
    • Config struct with env-tag support (PG_HOST, PG_PORT, PG_USER, PG_PASSWORD,
      PG_NAME, PG_SSL_MODE, PG_MAX_CONNS, PG_MIN_CONNS, connection lifetime fields)
    • UnitOfWork interface and NewUnitOfWork(logger, client) constructor using context injection
    • HandleError(err) error package-level function mapping pgx/PostgreSQL errors to xerrors:
      • UniqueViolationErrAlreadyExists with constraint name context
      • ForeignKeyViolationErrInvalidInput with table name context
      • CheckViolationErrInvalidInput with table and column context
      • pgx.ErrNoRowsErrNotFound
      • all other errors → ErrInternal
    • health.Checkable implementation at health.LevelCritical

    Installation

    go get code.nochebuena.dev/go/postgres@v0.9.0
    

    Requires Go 1.21 or later. Depends on code.nochebuena.dev/go/health,
    code.nochebuena.dev/go/launcher, code.nochebuena.dev/go/logz,
    code.nochebuena.dev/go/xerrors, and github.com/jackc/pgx/v5.

    Design Highlights

    pgx native types throughout. Executor uses pgconn.CommandTag, pgx.Rows, and
    pgx.Row directly. There is no database/sql adapter; this is an intentional design choice
    to give repository code access to pgx-specific features (named parameters, pgtype, etc.).

    No dbutil wrapper. Executor, Tx, Client, and Component are defined locally in
    this package using pgx types. The mysql module has its own independent Executor. The two
    are intentionally incompatible.

    UnitOfWork via context injection. NewUnitOfWork.Do begins a transaction, stores it in
    the context under an unexported key, and calls the provided function. GetExecutor(ctx) returns
    the transaction when one is present, otherwise the pool. Repositories need no awareness of
    whether they are inside a transaction.

    Error mapping by pgerrcode constants. HandleError uses errors.As to unwrap
    *pgconn.PgError and switches on pgerrcode constants, not message strings.

    Lifecycle-aware health check. HealthCheck delegates to Ping, which calls
    pgxpool.Pool.Ping. Priority is health.LevelCritical.

    Known Limitations & Edge Cases

    • No query builder. Repository code writes raw SQL strings. There is no DSL or prepared
      statement cache beyond what pgxpool provides natively.
    • No migration helper. Schema migrations are out of scope; use a dedicated tool such as
      golang-migrate or goose.
    • Health check uses pgxpool.Ping, not SELECT 1. Pool.Ping acquires a connection from
      the pool and calls the pgx-level ping. It does not execute a query, so it may not detect all
      forms of server-side unavailability.
    • Transaction stored in context is not safe to use after Do returns. Goroutines launched
      inside UnitOfWork.Do that outlive the callback will hold a reference to a committed or
      rolled-back transaction.

    v0.9.0 → v1.0.0 Roadmap

    • Evaluate adding a SELECT 1 health check option alongside the pool ping.
    • Consider exposing connection pool stats (idle, total, wait count) through the health check
      or a dedicated metrics hook.
    • Assess whether a BeginTx(ctx, opts) variant is needed for serialisable isolation.
    • Gather production feedback on connection pool defaults before hardening the config.
    Downloads