lock

package module
v8.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2018 License: MIT Imports: 8 Imported by: 71

README

redis-lock

Build Status GoDoc Go Report Card License

Simplified distributed locking implementation using Redis. For more information, please see examples.

Examples

import (
  "fmt"
  "time"

  "github.com/bsm/redis-lock"
  "github.com/go-redis/redis"
)

func main() {
	// Connect to Redis
	client := redis.NewClient(&redis.Options{
		Network:	"tcp",
		Addr:		"127.0.0.1:6379",
	})
	defer client.Close()

	// Obtain a new lock with default settings
	lock, err := lock.Obtain(client, "lock.foo", nil)
	if err != nil {
		fmt.Printf("ERROR: %s\n", err.Error())
		return
	} else if lock == nil {
		fmt.Println("ERROR: could not obtain lock")
		return
	}

	// Don't forget to unlock in the end
	defer lock.Unlock()

	// Run something
	fmt.Println("I have a lock!")
	time.Sleep(200 * time.Millisecond)

	// Renew your lock
	ok, err := lock.Lock()
	if err != nil {
		fmt.Printf("ERROR: %s\n", err.Error())
		return
	} else if !ok {
		fmt.Println("ERROR: could not renew lock")
		return
	}
	fmt.Println("I have renewed my lock!")

}

Documentation

Full documentation is available on GoDoc

Testing

Simply run:

make

Documentation

Overview

Example
// Connect to Redis
client := redis.NewClient(&redis.Options{
	Network: "tcp",
	Addr:    "127.0.0.1:6379",
})
defer client.Close()

// Create a new locker with default settings
locker := lock.New(client, "lock.foo", nil)

// Try to obtain lock
hasLock, err := locker.Lock()
if err != nil {
	panic(err.Error())
} else if !hasLock {
	fmt.Println("could not obtain lock!")
	return
}

// Don't forget to defer Unlock!
defer locker.Unlock()
fmt.Println("I have a lock!")

// Sleep and check if still locked afterwards.
time.Sleep(200 * time.Millisecond)
if locker.IsLocked() {
	fmt.Println("My lock has expired!")
}

// Renew your lock
renewed, err := locker.Lock()
if err != nil {
	panic(err.Error())
} else if !renewed {
	fmt.Println("could not renew lock!")
	return
}
fmt.Println("I have renewed my lock!")
Output:

I have a lock!
My lock has expired!
I have renewed my lock!

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrLockUnlockFailed     = errors.New("lock unlock failed")
	ErrLockNotObtained      = errors.New("lock not obtained")
	ErrLockDurationExceeded = errors.New("lock duration exceeded")
)

ErrLockNotObtained may be returned by Obtain() and Run() if a lock could not be obtained.

Functions

func Run

func Run(client RedisClient, key string, opts *Options, handler func()) error

Run runs a callback handler with a Redis lock. It may return ErrLockNotObtained if a lock was not successfully acquired.

Types

type Locker

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

Locker allows (repeated) distributed locking.

func New

func New(client RedisClient, key string, opts *Options) *Locker

New creates a new distributed locker on a given key.

func Obtain

func Obtain(client RedisClient, key string, opts *Options) (*Locker, error)

Obtain is a shortcut for New().Lock(). It may return ErrLockNotObtained if a lock was not successfully acquired.

func (*Locker) IsLocked

func (l *Locker) IsLocked() bool

IsLocked returns true if a lock is still being held.

func (*Locker) Lock

func (l *Locker) Lock() (bool, error)

Lock applies the lock, don't forget to defer the Unlock() function to release the lock after usage.

func (*Locker) LockWithContext

func (l *Locker) LockWithContext(ctx context.Context) (bool, error)

LockWithContext is like Lock but allows to pass an additional context which allows cancelling lock attempts prematurely.

func (*Locker) Unlock

func (l *Locker) Unlock() error

Unlock releases the lock

type Options

type Options struct {
	// The maximum duration to lock a key for
	// Default: 5s
	LockTimeout time.Duration

	// The number of time the acquisition of a lock will be retried.
	// Default: 0 = do not retry
	RetryCount int

	// RetryDelay is the amount of time to wait between retries.
	// Default: 100ms
	RetryDelay time.Duration
}

Options describe the options for the lock

type RedisClient

type RedisClient interface {
	SetNX(key string, value interface{}, expiration time.Duration) *redis.BoolCmd
	Eval(script string, keys []string, args ...interface{}) *redis.Cmd
	EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd
	ScriptExists(scripts ...string) *redis.BoolSliceCmd
	ScriptLoad(script string) *redis.StringCmd
}

RedisClient is a minimal client interface.

Jump to

Keyboard shortcuts

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