pgctx

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2026 License: MIT Imports: 4 Imported by: 0

README

pgctx

Neutral *pgxpool.Pool bridge for Go HTTP services.

import "github.com/palgroup/pgctx"

What it does

  • pgctx.PoolFunc — a contract: func(ctx context.Context) (*pgxpool.Pool, error).
  • pgctx.Middleware(poolFunc, onErr) — HTTP middleware that resolves a pool and injects it into request context.
  • pgctx.From(ctx) / pgctx.FromOK(ctx) — handlers/services read the pool back.
  • pgctx.With(ctx, pool) — for background workers that don't have an HTTP request.

Why

Modules shouldn't know where their pool comes from. A multi-tenant deployment resolves per-tenant pools via some registry; a single-tenant deployment hands back one long-lived pool. Both shapes plug the same PoolFunc into pgctx.Middleware — module code stays identical.

// Standalone: one pool for all requests
poolFunc := pgctx.PoolFunc(func(_ context.Context) (*pgxpool.Pool, error) {
    return pool, nil
})

// Multi-tenant: resolve per request
poolFunc := func(ctx context.Context) (*pgxpool.Pool, error) {
    tenantID := extractTenantID(ctx)
    return registry.Get(ctx, tenantID)
}

router.Use(pgctx.Middleware(poolFunc, errorHandler))

// Handlers read the pool without knowing the topology
func handle(w http.ResponseWriter, r *http.Request) {
    pool := pgctx.From(r.Context())
    // ...
}

Install

go get github.com/palgroup/pgctx

Go 1.26+ required (uses context, net/http, github.com/jackc/pgx/v5).

License

MIT.

Documentation

Overview

Package pgctx carries a *pgxpool.Pool through request contexts.

The package has no opinion on how the pool is created, cached, or routed. Deployments wire Middleware with any PoolFunc they like:

  • Standalone single-DB: PoolFunc returns the same *pgxpool.Pool always
  • Multi-tenant routed: PoolFunc resolves a per-tenant pool from ctx
  • Tests: use With(ctx, testPool) to inject directly

The module that imports pgctx sees only From(ctx) — it does not know whether there is one pool or many, what cache or router sits behind it, or even whether the DB is reached through a pooler.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoPool = errors.New("pgctx: no pool for this context")

ErrNoPool is the sentinel returned by adapters that cannot resolve a pool for the given context (e.g., tenant claim missing). Deployments may wrap or replace it.

Functions

func From

func From(ctx context.Context) *pgxpool.Pool

From extracts the pool injected by Middleware.

Panics when no pool is present: a handler reaching here without one means the middleware chain is misconfigured, and silent failure would be worse than a loud boot-time smoke-test crash. Callers that must tolerate missing pools should use FromOK.

func FromOK

func FromOK(ctx context.Context) (*pgxpool.Pool, bool)

FromOK is the non-panicking form of From.

func Middleware

func Middleware(fn PoolFunc, onErr ErrorHandler) func(http.Handler) http.Handler

Middleware resolves the pool via fn and injects it into the request context. Modules read it back with From().

If fn returns an error, onErr is called (or a 503 is written) and the handler chain is aborted.

func With

func With(ctx context.Context, pool *pgxpool.Pool) context.Context

With returns a context with the given pool attached.

Used by tests and by background workers that resolve the tenant from message payloads instead of HTTP headers: extract the tenant, get the pool from whatever adapter is in use, then With(ctx, pool) before calling service/repository code.

Types

type ErrorHandler

type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)

ErrorHandler turns a PoolFunc error into an HTTP response. Pass nil to Middleware to use defaultErrorHandler (plain 503).

type PoolFunc

type PoolFunc func(ctx context.Context) (*pgxpool.Pool, error)

PoolFunc returns the pool that should serve a given request context. It receives the request's context (which may carry tenant claims, tracing spans, etc.) so adapters can route accordingly.

Returning (nil, err) causes Middleware to write 503 and abort the chain.

Jump to

Keyboard shortcuts

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