lockmanager
Lock Manager Package
The Lock Manager package provides a unified and extensible distributed locking interface for Go applications. It offers a consistent way to implement distributed locks across different services, making it easy to coordinate access to shared resources in distributed systems.
Features
Unified Interface: Consistent API for different lock implementations
Redis Implementation: Built-in support for Redis-based distributed locks
Customizable Lock Options: Configure lock behavior with options like TTL and retry parameters
Context Support: All operations respect context cancellation and deadlines
LocalLock Implementation: Simple in-memory lock for local use cases
Custom Token Generation: Optionally provide custom token generation logic
Auto Cleanup: Locks are automatically cleaned up when ttl expires
Usage
Locking Interface
The core of the package is the LockManager
interface:
type LockManager interface {
// Acquire attempts to acquire a lock with given key and TTL.
// Optionally accepts a token; otherwise, one is auto-generated.
Acquire(ctx context.Context, key string, ttl time.Duration, token ...string) (string, error)
// Release attempts to release a lock with the given key and token.
Release(ctx context.Context, key string, token string) error
}
🚀 Getting Started with Redis
Create Redis LockManager
import (
"github.com/redis/go-redis/v9"
redsyncLocker "github.com/kittipat1413/go-common/framework/lockmanager/redsync"
)
func main() {
// Setup Redis client
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
// Initialize LockManager
manager := redsyncLocker.NewRedsyncLockManager(client)
}
🔐 Acquire Lock
ctx := context.Background()
token, err := lockManager.Acquire(ctx, "email-job-lock", 5*time.Second)
if err != nil {
if errors.Is(err, locker.ErrLockAlreadyTaken) {
// Handle lock contention
}
log.Fatalf("failed to acquire lock: %v", err)
}
🔓 Release Lock
err = lockManager.Release(ctx, "email-job-lock", token)
if err != nil {
if errors.Is(err, locker.ErrUnlockNotPermitted) {
// You don't own this lock
}
log.Fatalf("failed to release lock: %v", err)
}
⚙️ Advanced Configuration
manager := redsyncLocker.NewRedsyncLockManager(
client,
redsyncLocker.WithTokenGenerator(func(key string) string {
return "lock-token-for:" + key
}),
redsyncLocker.WithRedsyncOptions(
redsync.WithTries(5), // Retry up to 5 times
redsync.WithRetryDelay(50*time.Millisecond), // Wait 50ms between retries
),
)
Example
You can find a complete working example in the repository under framework/lockmanager/example.
Last updated