95 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			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,
 | |
| 	}
 | |
| }
 |