// 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, } }