distributedlockcfg

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 8, 2026 License: AGPL-3.0 Imports: 17 Imported by: 0

Documentation

Overview

Package distributedlockcfg selects and builds a distributedlock.Locker, or a ScopedLocker, from configuration: Redis, Postgres, memory, or noop.

Only the Postgres provider needs the database.Client both constructors take; every other provider is passed nil. Ask cfg.RequiresDatabase rather than comparing Provider yourself — the comparison is against the normalized name, and a config spelling "POSTGRES" dispatched to the Postgres locker while skipping the database lookup that would have supplied it.

The two constructors do not build the same thing from the same provider: the Postgres ScopedLocker is the native transaction-scoped implementation, which waits server-side and has no TTL, while Redis and memory get the generic scoped adapter wrapped around their Locker.

Index

Constants

View Source
const (
	// RedisProvider selects the redis-backed distributedlock.Locker implementation.
	RedisProvider = "redis"
	// PostgresProvider selects the postgres-backed distributedlock.Locker implementation.
	PostgresProvider = "postgres"
	// MemoryProvider selects the in-memory distributedlock.Locker implementation.
	MemoryProvider = "memory"
	// NoopProvider selects the no-op distributedlock.Locker implementation,
	// whose Acquire always succeeds. It must be chosen deliberately: an unset or
	// unrecognized provider is an error, because silently removing mutual
	// exclusion looks exactly like a system that never contends.
	NoopProvider = "noop"
)

Variables

This section is empty.

Functions

func NewLocker

func NewLocker(
	ctx context.Context,
	cfg *Config,
	db database.Client,
	opts ...Option,
) (distributedlock.Locker, error)

NewLocker constructs a distributedlock.Locker for the configured provider. The db argument is required only when Provider is PostgresProvider; pass nil otherwise. An unknown or empty provider is an error.

func NewScopedLocker

func NewScopedLocker(
	ctx context.Context,
	cfg *Config,
	db database.Client,
	opts ...Option,
) (distributedlock.ScopedLocker, error)

NewScopedLocker constructs a distributedlock.ScopedLocker for the configured provider. The postgres provider gets the native transaction-scoped implementation (server-side waiting, no TTL); redis and memory wrap their Locker in the generic scoped adapter with its defaults. As with NewLocker, db is required only for PostgresProvider, and an unknown or empty provider is an error.

func RegisterLocker

func RegisterLocker(i do.Injector)

RegisterLocker registers a distributedlock.Locker with the injector.

Prerequisites: *Config must be registered in the injector before the Locker is invoked. A database.Client is only required when the config's provider is postgres, so a redis- or memory-locked service can build without one.

func RegisterScopedLocker

func RegisterScopedLocker(i do.Injector)

RegisterScopedLocker registers a distributedlock.ScopedLocker with the injector.

Prerequisites: *Config must be registered in the injector before the Locker is invoked. A database.Client is only required when the config's provider is postgres, so a redis- or memory-locked service can build without one.

Types

type Config

type Config struct {
	Redis          *redislock.Config         `env:",init"    envPrefix:"REDIS_"            json:"redis,omitempty"               yaml:"redis,omitempty"`
	Postgres       *pglock.Config            `env:",init"    envPrefix:"POSTGRES_"         json:"postgres,omitempty"            yaml:"postgres,omitempty"`
	Provider       string                    `env:"PROVIDER" json:"provider,omitempty"     yaml:"provider,omitempty"`
	CircuitBreaker circuitbreakingcfg.Config `env:",init"    envPrefix:"CIRCUIT_BREAKING_" json:"circuitBreakerConfig,omitzero" yaml:"circuitBreakerConfig,omitempty"`
	// contains filtered or unexported fields
}

Config dispatches to a distributedlock provider implementation.

func (*Config) RequiresDatabase

func (cfg *Config) RequiresDatabase() bool

RequiresDatabase reports whether building a locker from cfg needs a database.Client. Only the postgres locker does; every other provider takes nil.

It is a method rather than a comparison each caller writes out, because each caller that wrote it out wrote it against the raw Provider string: a config naming "POSTGRES" dispatched to the postgres locker and skipped the database lookup, then failed with ErrNilDatabaseClient on a container that had one registered all along.

func (*Config) ValidateWithContext

func (cfg *Config) ValidateWithContext(ctx context.Context) error

ValidateWithContext validates a Config struct. Provider is required: the noop locker is reachable only by naming it.

The sub-config for a provider that was not selected is skipped rather than merely unguarded: ozzo validates any non-nil pointer to a Validatable once a field's rules have run, and `env:",init"` leaves every sub-config non-nil. A validation.When guard alone stops the Required rule and nothing else, so Redis addresses were demanded of the memory and noop lockers. Releasing the zero sub-configs instead would not do: both carry envDefault fields, so neither is zero once the environment has been parsed.

The selection is read normalized, matching dispatch: a "REDIS" that knownProvider accepts and NewLocker dispatches on would otherwise skip the very block it is about to use.

type Option

type Option func(*options)

Option configures how this package's constructors assemble their lockers.

The observability dependencies are options rather than parameters because every one of them is genuinely optional: an absent logger logs nowhere, an absent tracer provider traces nowhere, and an absent metrics provider records nothing. Requiring them positionally made a caller that wanted none of the three name all three anyway, usually as noops.

func WithLogger

func WithLogger(logger logging.Logger) Option

WithLogger attaches a logger. An absent logger logs nowhere.

func WithMetricsProvider

func WithMetricsProvider(metricsProvider metrics.Provider) Option

WithMetricsProvider attaches a metrics provider. An absent provider records nothing.

func WithPillars

func WithPillars(p *observability.Pillars) Option

WithPillars attaches a logger, tracer provider, and metrics provider in one go, for the common case where a caller has already built them together. A nil Pillars attaches nothing.

It is applied in order with the individual options, so a caller can hand over its pillars and then override one of them.

func WithTracerProvider

func WithTracerProvider(tracerProvider tracing.Provider) Option

WithTracerProvider attaches a tracer provider, enabling spans on the instrumented operations. An absent tracer provider traces nowhere.

Jump to

Keyboard shortcuts

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