distributedlock

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Apr 13, 2026 License: AGPL-3.0 Imports: 3 Imported by: 0

Documentation

Overview

Package distributedlock provides a pessimistic mutual-exclusion atom for coordinating exclusive access to a named resource across processes. Provider implementations live in subpackages and are selected at runtime via distributedlock/config.

The interface is intentionally narrow: Acquire/Release/Refresh, with no built-in retry loop or queueing. Callers compose Acquire with platform/retry, the platform circuit breaker, or their own backoff strategy. Higher-level concerns such as leader election, distributed cron, and exactly-once batch execution are compositions on top of this atom and live in consuming applications, not in platform.

Provider semantics differ in one important respect: the redis and memory providers enforce TTLs natively, while the postgres provider's TTL is advisory only — the underlying pg_advisory_lock is held until either Release is called or the dedicated session is closed. See distributedlock/postgres for details.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrLockNotAcquired indicates Acquire could not obtain the lock immediately
	// because another caller currently holds it. Callers that want to wait should
	// compose Acquire with a retry/backoff loop themselves — the Locker interface
	// does not retry internally.
	ErrLockNotAcquired = platformerrors.New("lock not acquired")
	// ErrLockNotHeld indicates Release or Refresh was called on a lock the caller
	// no longer owns. Reasons include TTL expiration, the lock being stolen by
	// another caller after expiration, double-release, or — for the postgres
	// provider — the underlying connection having been closed out from under us.
	ErrLockNotHeld = platformerrors.New("lock not held")
	// ErrNilConfig indicates a nil provider config was passed to a constructor.
	ErrNilConfig = platformerrors.New("nil distributedlock config")
	// ErrInvalidTTL indicates a non-positive TTL was supplied to Acquire or Refresh.
	ErrInvalidTTL = platformerrors.New("invalid lock TTL")
	// ErrEmptyKey indicates an empty key was supplied to Acquire.
	ErrEmptyKey = platformerrors.New("empty lock key")
	// ErrNilDatabaseClient indicates a nil database.Client was passed to a postgres-
	// backed provider.
	ErrNilDatabaseClient = platformerrors.New("nil database client")
)

Functions

This section is empty.

Types

type Lock

type Lock interface {
	// Key returns the lock name this handle owns.
	Key() string
	// TTL returns the configured expiration for this lock at the time it was
	// last acquired or refreshed. It is not adjusted as time passes.
	TTL() time.Duration
	// Release releases the lock. Returns ErrLockNotHeld if the caller no longer
	// owns the lock (expiration, theft after expiration, double-release).
	Release(ctx context.Context) error
	// Refresh extends the lock's TTL to the supplied value. Returns
	// ErrLockNotHeld if the caller no longer owns the lock.
	Refresh(ctx context.Context, ttl time.Duration) error
}

Lock is the handle returned from Acquire. It carries the ownership token internally and is the only way to release or refresh the lock. Lock handles are owned by a single goroutine — they must not be shared.

type Locker

type Locker interface {
	// Acquire attempts to acquire the lock named `key` with the supplied TTL.
	// Returns ErrLockNotAcquired immediately if the lock is currently held by
	// another caller. There is no internal retry — callers wrap with
	// retry/backoff themselves.
	Acquire(ctx context.Context, key string, ttl time.Duration) (Lock, error)
	// Ping verifies the underlying backend is reachable.
	Ping(ctx context.Context) error
	// Close releases any backend resources held by the Locker. Outstanding Lock
	// handles obtained from this Locker may become invalid after Close.
	Close() error
}

Locker is the manager atom. It hands out Lock handles keyed by string. Locker implementations must be safe for concurrent use; the Lock handles they return are owned by the goroutine that called Acquire and are NOT goroutine-safe.

Directories

Path Synopsis
Package mock provides mock implementations of the distributedlock package's interfaces.
Package mock provides mock implementations of the distributedlock package's interfaces.
Package postgres implements distributedlock.Locker against PostgreSQL session- scoped advisory locks (pg_try_advisory_lock).
Package postgres implements distributedlock.Locker against PostgreSQL session- scoped advisory locks (pg_try_advisory_lock).

Jump to

Keyboard shortcuts

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