micro/sync/lock/redis/redis.go
2019-05-31 00:43:23 +01:00

95 lines
1.5 KiB
Go

// Package redis is a redis implemenation of lock
package redis
import (
"errors"
"sync"
"time"
"github.com/go-redsync/redsync"
"github.com/micro/go-micro/sync/lock"
)
type redisLock struct {
sync.Mutex
locks map[string]*redsync.Mutex
opts lock.Options
c *redsync.Redsync
}
func (r *redisLock) Acquire(id string, opts ...lock.AcquireOption) error {
var options lock.AcquireOptions
for _, o := range opts {
o(&options)
}
var ropts []redsync.Option
if options.Wait > time.Duration(0) {
ropts = append(ropts, redsync.SetRetryDelay(options.Wait))
ropts = append(ropts, redsync.SetTries(1))
}
if options.TTL > time.Duration(0) {
ropts = append(ropts, redsync.SetExpiry(options.TTL))
}
m := r.c.NewMutex(r.opts.Prefix+id, ropts...)
err := m.Lock()
if err != nil {
return err
}
r.Lock()
r.locks[id] = m
r.Unlock()
return nil
}
func (r *redisLock) Release(id string) error {
r.Lock()
defer r.Unlock()
m, ok := r.locks[id]
if !ok {
return errors.New("lock not found")
}
unlocked := m.Unlock()
delete(r.locks, id)
if !unlocked {
return errors.New("lock not unlocked")
}
return nil
}
func (r *redisLock) String() string {
return "redis"
}
func NewLock(opts ...lock.Option) lock.Lock {
var options lock.Options
for _, o := range opts {
o(&options)
}
nodes := options.Nodes
if len(nodes) == 0 {
nodes = []string{"127.0.0.1:6379"}
}
rpool := redsync.New([]redsync.Pool{&pool{
addrs: nodes,
}})
return &redisLock{
locks: make(map[string]*redsync.Mutex),
opts: options,
c: rpool,
}
}