Documentation
¶
Overview ¶
Package postgres implements distributedlock.Locker against PostgreSQL session- scoped advisory locks (pg_try_advisory_lock). It uses an existing platform/database.Client for connection management.
TTL semantics: PostgreSQL advisory locks have no native TTL, so this provider enforces the TTL client-side. Acquire stamps an expiry, Expired reports against it, and Refresh both verifies the underlying session is alive and extends the expiry by the TTL it is given.
What that does and does not buy you is worth being precise about. The expiry is this process's own bookkeeping: it stops a caller from believing it still holds a lock it has held past its TTL. It is not enforced by the database, so a process that ignores Expired keeps the advisory lock until Release is called or the dedicated session ends (a network failure, or Locker.Close). Another process will not acquire the lock merely because the first one's TTL lapsed — for a hard, server-side bound, use a lease table rather than advisory locks.
Each Acquire reserves a dedicated *sql.Conn from the database client's pool so that the matching pg_advisory_unlock targets the same session. The Locker tracks outstanding connections internally and releases all of them on Close.
Index ¶
- Constants
- func NewPostgresLocker(cfg *Config, db database.Client, cb circuitbreaking.CircuitBreaker, ...) (distributedlock.Locker, error)
- func NewPostgresScopedLocker(cfg *Config, db database.Client, cb circuitbreaking.CircuitBreaker, ...) (distributedlock.ScopedLocker, error)
- type Config
- type Option
Constants ¶
const DefaultConnWaitTimeout = 5 * time.Second
DefaultConnWaitTimeout bounds how long Acquire waits to reserve a write-pool connection before giving up. See Config.ConnWaitTimeout.
Variables ¶
This section is empty.
Functions ¶
func NewPostgresLocker ¶
func NewPostgresLocker( cfg *Config, db database.Client, cb circuitbreaking.CircuitBreaker, opts ...Option, ) (distributedlock.Locker, error)
NewPostgresLocker constructs a new postgres-backed distributedlock.Locker.
func NewPostgresScopedLocker ¶
func NewPostgresScopedLocker( cfg *Config, db database.Client, cb circuitbreaking.CircuitBreaker, opts ...Option, ) (distributedlock.ScopedLocker, error)
NewPostgresScopedLocker constructs a transaction-scoped distributedlock.ScopedLocker. Unlike NewPostgresLocker it needs only the safe database.Client surface (WithTransaction), not RawAccess.
fn runs while the calling transaction holds the advisory lock, but receives only a context: any database work fn performs goes through its own connections and is NOT part of the lock-holding transaction. WithLock waits in the database (pg_advisory_xact_lock queues server-side, so waiters need no polling and are granted the lock in request order); each in-flight call occupies one write-pool connection for fn's duration.
Types ¶
type Config ¶
type Config struct {
// Namespace is mixed into the lock-id hash so independent services sharing a
// Postgres cluster do not collide on the same advisory-lock id space.
Namespace int32 `env:"NAMESPACE" envDefault:"0" json:"namespace" yaml:"namespace"`
// ConnWaitTimeout bounds how long Acquire will wait to reserve a connection
// from the write pool. Each held lock pins one write connection for its whole
// lifetime, so a saturated pool would otherwise make Acquire block indefinitely
// in database/sql's Conn(). When the wait is exceeded, Acquire returns
// distributedlock.ErrLockNotAcquired instead of blocking. Zero uses
// DefaultConnWaitTimeout; a negative value disables the bound (wait forever).
ConnWaitTimeout time.Duration `env:"CONN_WAIT_TIMEOUT" envDefault:"5s" json:"connWaitTimeout" yaml:"connWaitTimeout"`
}
Config configures a Postgres-backed distributed locker. Namespace is mixed into the lock-id hash so independent services that share a Postgres cluster do not collide on the same advisory-lock id space.
type Option ¶
type Option func(*options)
Option configures the postgres-backed lockers this package constructs. The zero configuration works: an absent logger logs nowhere, an absent tracer provider traces nowhere, and an absent metrics provider records nothing.
func WithMetricsProvider ¶
WithMetricsProvider attaches a metrics provider for the locker's counters and latency histogram.
func WithTracerProvider ¶
func WithTracerProvider(tracerProvider tracing.TracerProvider) Option
WithTracerProvider attaches a tracer provider, enabling spans on every lock operation.