lock

package
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package lock builds a config-selected core/interfaces.Locker — a DistributedLock (keyed, token-fenced, best-effort) plus Hold, the managed acquire-with-watchdog helper a single-active-operation guard depends on.

NewFromConfig chooses a backend from a Kind string — local (in-process, dev / replica=1) or redis (cross-pod, staging/prod) — mirroring the foundation/logger.NewFromConfig and clients/cache factory pattern, and wraps it in a Locker (NewLocker). The redis backend reuses the live go-redis client from the cache (clients/cache/redis.Cache.Client), so no second connection pool is opened.

Hold acquires a key and keeps its lease alive with a background watchdog; the context it returns is cancelled the instant the lease is lost, so a losing pod's in-flight work is stopped rather than left running under a lock it no longer owns. Key naming is the caller's.

Cross-cutting concerns are composed by the decorators subpackage (resilience: retry, circuit-breaker, timeout; observability: logging, metrics, tracing), wired by NewFromConfig from the Config collaborators.

Scope boundary: this package ships both backends, the factory, the decorator stack, and Hold. Wiring them (config + shared redis client + observability/resilience deps → Locker) and choosing the call sites and key names belong to the consumer's composition root.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewFromConfig

func NewFromConfig(
	cfg *Config,
	client *goredis.Client,
) (interfaces.Locker, error)

NewFromConfig builds the configured Locker: it selects a DistributedLock backend by Kind, wraps it in the resilience + observability decorator stack (from the Config collaborators — each optional/nil-safe), and returns a Locker whose Hold renews on RenewInterval over the decorated backend. The client is required only for KindRedis (the shared go-redis client reused from the cache); it is ignored for KindLocal. It fails loudly on an unknown kind, a non-positive TTL or RenewInterval, a RenewInterval that exceeds TTL/3, or a redis kind with no client.

func NewLocker

func NewLocker(
	lock interfaces.DistributedLock,
	renewInterval time.Duration,
) interfaces.Locker

NewLocker wraps a DistributedLock with the renewal cadence Hold uses, yielding a Locker. Exposed so callers (and tests) can compose Hold over any DistributedLock — e.g. a mock or a backend built directly; NewFromConfig builds one over the config-selected backend.

Types

type Config

type Config struct {
	// Logger drives the logging decorator; nil skips it.
	Logger interfaces.Logger

	// Metrics drives the metrics decorator; nil skips it.
	Metrics interfaces.Metrics

	// Tracer drives the tracing decorator; nil skips it.
	Tracer interfaces.Tracer

	// Retrier drives the retry decorator (transient-error retries); nil skips it.
	Retrier interfaces.Retrier

	// CircuitBreaker drives the circuit-breaker decorator; nil skips it.
	CircuitBreaker interfaces.CircuitBreaker

	// Name labels the lock in metrics, spans, and logs (default "lock").
	Name string

	// Kind selects the backend (local | redis).
	Kind Kind

	// TTL is the lease duration applied on Acquire and extended by Renew.
	TTL time.Duration

	// RenewInterval is the watchdog's renew cadence in Hold.
	RenewInterval time.Duration

	// OpTimeout bounds each backend operation via the timeout decorator; zero
	// skips it.
	OpTimeout time.Duration
}

Config selects and tunes the lock. Kind picks the backend; TTL is the lease duration a holder gets on Acquire (and Renew extends); RenewInterval is how often Hold's watchdog renews. RenewInterval must be ≤ TTL/3 so a couple of missed renew ticks cannot expire a live lease.

type Kind

type Kind int

Kind selects which DistributedLock backend NewFromConfig builds.

const (
	// KindLocal is the in-process backend: correct for a single replica (dev /
	// replica=1), no external dependency.
	KindLocal Kind = iota

	// KindRedis is the cross-pod backend over a shared Redis client
	// (staging/prod, multi-replica).
	KindRedis
)

func (Kind) String

func (k Kind) String() string

String returns the config token for the kind.

Directories

Path Synopsis
Package decorators composes cross-cutting concerns — resilience (retry, circuit-breaker, timeout) and observability (logging, metrics, tracing) — around any core/interfaces.DistributedLock, without touching the backend.
Package decorators composes cross-cutting concerns — resilience (retry, circuit-breaker, timeout) and observability (logging, metrics, tracing) — around any core/interfaces.DistributedLock, without touching the backend.
Package local provides an in-process DistributedLock backend for single-pod deployments (dev / replica=1), where cross-process coordination is unnecessary.
Package local provides an in-process DistributedLock backend for single-pod deployments (dev / replica=1), where cross-process coordination is unnecessary.
Package redis provides a cross-pod DistributedLock backend over Redis, for multi-replica deployments (staging/prod).
Package redis provides a cross-pod DistributedLock backend over Redis, for multi-replica deployments (staging/prod).

Jump to

Keyboard shortcuts

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