105 lines
1.8 KiB
Go
105 lines
1.8 KiB
Go
|
// Package consul is a consul implemenation of lock
|
||
|
package consul
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/hashicorp/consul/api"
|
||
|
lock "github.com/micro/go-micro/sync/lock"
|
||
|
)
|
||
|
|
||
|
type consulLock struct {
|
||
|
sync.Mutex
|
||
|
|
||
|
locks map[string]*api.Lock
|
||
|
opts lock.Options
|
||
|
c *api.Client
|
||
|
}
|
||
|
|
||
|
func (c *consulLock) Acquire(id string, opts ...lock.AcquireOption) error {
|
||
|
var options lock.AcquireOptions
|
||
|
for _, o := range opts {
|
||
|
o(&options)
|
||
|
}
|
||
|
|
||
|
if options.Wait <= time.Duration(0) {
|
||
|
options.Wait = api.DefaultLockWaitTime
|
||
|
}
|
||
|
|
||
|
ttl := fmt.Sprintf("%v", options.TTL)
|
||
|
if options.TTL <= time.Duration(0) {
|
||
|
ttl = api.DefaultLockSessionTTL
|
||
|
}
|
||
|
|
||
|
l, err := c.c.LockOpts(&api.LockOptions{
|
||
|
Key: c.opts.Prefix + id,
|
||
|
LockWaitTime: options.Wait,
|
||
|
SessionTTL: ttl,
|
||
|
})
|
||
|
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
_, err = l.Lock(nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
c.Lock()
|
||
|
c.locks[id] = l
|
||
|
c.Unlock()
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (c *consulLock) Release(id string) error {
|
||
|
c.Lock()
|
||
|
defer c.Unlock()
|
||
|
l, ok := c.locks[id]
|
||
|
if !ok {
|
||
|
return errors.New("lock not found")
|
||
|
}
|
||
|
err := l.Unlock()
|
||
|
delete(c.locks, id)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (c *consulLock) String() string {
|
||
|
return "consul"
|
||
|
}
|
||
|
|
||
|
func NewLock(opts ...lock.Option) lock.Lock {
|
||
|
var options lock.Options
|
||
|
for _, o := range opts {
|
||
|
o(&options)
|
||
|
}
|
||
|
|
||
|
config := api.DefaultConfig()
|
||
|
|
||
|
// set host
|
||
|
// config.Host something
|
||
|
// check if there are any addrs
|
||
|
if len(options.Nodes) > 0 {
|
||
|
addr, port, err := net.SplitHostPort(options.Nodes[0])
|
||
|
if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
|
||
|
port = "8500"
|
||
|
config.Address = fmt.Sprintf("%s:%s", options.Nodes[0], port)
|
||
|
} else if err == nil {
|
||
|
config.Address = fmt.Sprintf("%s:%s", addr, port)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
client, _ := api.NewClient(config)
|
||
|
|
||
|
return &consulLock{
|
||
|
locks: make(map[string]*api.Lock),
|
||
|
opts: options,
|
||
|
c: client,
|
||
|
}
|
||
|
}
|