distlock

package
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package distlock provides Redis-backed distributed locking with two usage modes: fail-hard and fail-silent.

The locker wraps the bsm/redislock library and ensures locks are always released via defer, even if the handler panics. Lock release failures are logged as warnings but do not cause errors.

Basic usage (fail-hard):

locker := distlock.New(redisClient)
err := locker.WithLock(ctx, "resource:123", 30*time.Second, func() error {
    // Exclusive access to resource:123 for 30 seconds
    return updateResource()
})
if err != nil && errors.Is(err, distlock.ErrLockNotObtained) {
    return fmt.Errorf("failed to acquire lock")
}

For background jobs that should silently skip if the lock is unavailable:

err := locker.TryWithLock(ctx, "job:cleanup", 5*time.Minute, cleanupHandler)
// ErrLockNotObtained is swallowed and logged at debug level

Lock TTL is enforced by Redis; the handler should complete well before the TTL expires.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrLockNotObtained = redislock.ErrNotObtained

Functions

This section is empty.

Types

type Locker

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

func New

func New(redisClient redis.UniversalClient) *Locker

func (*Locker) TryWithLock

func (l *Locker) TryWithLock(ctx context.Context, key string, ttl time.Duration, handler func() error) error
Example

ExampleLocker_TryWithLock shows fail-silent locking for background jobs: when the lock is unavailable the handler is skipped without an error. (Not run: requires a Redis server.)

client := redis.NewClient(&redis.Options{Addr: "localhost:6379"}) //nolint:exhaustruct
locker := distlock.New(client)

_ = locker.TryWithLock(context.Background(), "jobs:cleanup", 5*time.Minute, func() error {
	// Runs only on the instance that obtained the lock.
	return nil
})

func (*Locker) WithLock

func (l *Locker) WithLock(ctx context.Context, key string, ttl time.Duration, handler func() error) error
Example

ExampleLocker_WithLock shows fail-hard locking: the caller decides what to do when the lock is held elsewhere. (Not run: requires a Redis server.)

client := redis.NewClient(&redis.Options{Addr: "localhost:6379"}) //nolint:exhaustruct
locker := distlock.New(client)

err := locker.WithLock(context.Background(), "resource:123", 30*time.Second, func() error {
	// Exclusive access to resource:123 for up to 30 seconds.
	return nil
})
if errors.Is(err, distlock.ErrLockNotObtained) {
	fmt.Println("another instance holds the lock")
}

Jump to

Keyboard shortcuts

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