The package-doc examples showed a fictional launcher.Register / health.Register API (and launcher.Append as a package func). Corrected to the real wiring: lc.Append + web/health.NewHandler(...).ServeHTTP. Documentation-only. No code, API, or dependency changes; version stays v1.1.0 (the v1.1.0 tag is moved to include this fix). Verified by compiling the corrected pattern against the real API.
62 lines
2.2 KiB
Go
62 lines
2.2 KiB
Go
// Package postgres provides a pgx-backed PostgreSQL client with lifecycle management,
|
|
// health checks, and unit-of-work transaction support for Einherjar applications.
|
|
//
|
|
// # Overview
|
|
//
|
|
// [New] returns a [Component] that manages a [pgxpool.Pool] connection pool,
|
|
// satisfies the [lifecycle.Component] lifecycle hooks (OnInit, OnStart, OnStop),
|
|
// and implements [observability.Checkable] with critical priority.
|
|
//
|
|
// [NewUnitOfWork] wraps multiple repository operations in a single transaction
|
|
// via context injection — no transaction object is passed between functions.
|
|
//
|
|
// # Lifecycle Registration
|
|
//
|
|
// db := postgres.New(logger, cfg)
|
|
// lc.Append(db) // lifecycle: OnInit → OnStart → OnStop
|
|
//
|
|
// db satisfies [observability.Checkable], so it can back a health endpoint via
|
|
// web/health.NewHandler:
|
|
//
|
|
// srv.Get("/health", health.NewHandler(logger, db).ServeHTTP)
|
|
//
|
|
// # Querying
|
|
//
|
|
// Repository code receives a [Provider] or [Executor] and calls [Provider.GetExecutor]
|
|
// to obtain the active transaction (if inside a [UnitOfWork]) or the pool:
|
|
//
|
|
// exec := db.GetExecutor(ctx)
|
|
// row := exec.QueryRow(ctx, "SELECT id FROM users WHERE email = $1", email)
|
|
// if err := row.Scan(&id); err != nil {
|
|
// return db.HandleError(err) // maps pgx.ErrNoRows → ErrNotFound, etc.
|
|
// }
|
|
//
|
|
// # Unit of Work
|
|
//
|
|
// [NewUnitOfWork] wraps operations in a single transaction. The transaction is
|
|
// injected into the context; [Provider.GetExecutor] returns it automatically.
|
|
//
|
|
// uow := postgres.NewUnitOfWork(logger, db)
|
|
// err := uow.Do(ctx, func(ctx context.Context) error {
|
|
// exec := db.GetExecutor(ctx) // returns active Tx
|
|
// _, err := exec.Exec(ctx, "INSERT INTO orders ...")
|
|
// return err
|
|
// })
|
|
//
|
|
// # Error Handling
|
|
//
|
|
// [HandleError] translates pgx and PostgreSQL error codes into typed
|
|
// [xerrors] values. Call it at every point where a pgx error is first observed:
|
|
//
|
|
// if err := row.Scan(&out); err != nil {
|
|
// return db.HandleError(err)
|
|
// }
|
|
//
|
|
// Mapped codes:
|
|
// - UniqueViolation → ErrAlreadyExists
|
|
// - ForeignKeyViolation → ErrInvalidInput
|
|
// - CheckViolation → ErrInvalidInput
|
|
// - pgx.ErrNoRows → ErrNotFound
|
|
// - all others → ErrInternal
|
|
package postgres
|