memory

package
v10.1.0 Latest Latest
Warning

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

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

Documentation

Overview

Package memory implements distributedlock.Locker over a map and a mutex.

It is not distributed

The name of the parent package is about the interface, not about this implementation. Mutual exclusion here extends exactly as far as one *Locker value: two replicas each hold their own map, so both acquire the same key at the same moment and neither learns of the other. Nothing detects that, and nothing reports it — the second holder's Acquire succeeds, and whatever the lock was protecting runs twice.

Two Lockers built in the same process do not exclude each other either, for the same reason. The lock's scope is the value, not the key.

So it is the right choice for tests, for a single-replica deployment, and as a readable statement of the semantics the other providers implement. It is the wrong choice anywhere the answer to "what happens if this runs twice" is not "nothing" — a scheduled job, a leader election, an exactly-once batch. Those want the redis or postgres provider, where the state lives outside any one process.

Semantics

TTLs are enforced by this process's clock, and lazily: an expired key is reclaimed when it is acquired again, and by an opportunistic sweep on each Acquire. Release and Refresh check the ownership token as well as the expiry, so a caller cannot release a key whose lock has already lapsed and been taken by someone else — that reports distributedlock.ErrLockNotHeld.

Nothing here fails from unavailability: Ping always succeeds, there is no circuit breaker, and no network call can time out mid-hold. Close drops every held lock at once, after which outstanding handles report ErrLockNotHeld.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Locker

type Locker struct {
	// contains filtered or unexported fields
}

Locker is a single-process distributedlock.Locker. It uses a sync.Mutex over an in-memory map and lazy expiration on each Acquire — there is no background goroutine. It is intended for tests, single-replica deployments, and as a clear reference implementation of the lock semantics.

func NewLocker

func NewLocker(opts ...Option) (*Locker, error)

NewLocker constructs a new in-memory Locker.

func (*Locker) Acquire

func (l *Locker) Acquire(ctx context.Context, key string, ttl time.Duration) (distributedlock.Lock, error)

Acquire implements distributedlock.Locker.

func (*Locker) Close

func (l *Locker) Close() error

Close drops all currently held locks. After Close, outstanding handles will see ErrLockNotHeld on Release/Refresh.

func (*Locker) Ping

func (*Locker) Ping(_ context.Context) error

Ping implements distributedlock.Locker.

type Option

type Option func(*options)

Option configures the in-memory Locker this package constructs. The zero configuration works: an absent logger logs nowhere, an absent tracer provider traces nowhere, an absent metrics provider records nothing, and an absent clock reads the wall clock.

func WithClock

func WithClock(c clock.Clock) Option

WithClock swaps the source of time this Locker makes its TTL decisions against. An absent clock reads the wall clock.

Expiry is the whole of this backend's semantics — whether a key is still held, whether a release still owns it, what a refresh extends to — and all of it ran off time.Now(), so a test for any of it had to sleep through a real TTL. The siblings that talk to Redis and Postgres delegate expiry to the server; this one implements it, which is exactly why it is the one that needs a clock.

func WithLogger

func WithLogger(logger logging.Logger) Option

WithLogger attaches a logger.

func WithMetricsProvider

func WithMetricsProvider(metricsProvider metrics.Provider) Option

WithMetricsProvider attaches a metrics provider for the locker's counters and latency histogram.

func WithTracerProvider

func WithTracerProvider(tracerProvider tracing.Provider) Option

WithTracerProvider attaches a tracer provider, enabling spans on every lock operation.

Jump to

Keyboard shortcuts

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