gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/sync/lock/etcd/etcd.go (about) 1 // Package etcd is an etcd implementation of lock 2 package etcd 3 4 import ( 5 "context" 6 "errors" 7 "log" 8 "path" 9 "strings" 10 "sync" 11 12 client "github.com/coreos/etcd/clientv3" 13 cc "github.com/coreos/etcd/clientv3/concurrency" 14 "gitee.com/liuxuezhan/go-micro-v1.18.0/sync/lock" 15 ) 16 17 type etcdLock struct { 18 opts lock.Options 19 path string 20 client *client.Client 21 22 sync.Mutex 23 locks map[string]*elock 24 } 25 26 type elock struct { 27 s *cc.Session 28 m *cc.Mutex 29 } 30 31 func (e *etcdLock) Acquire(id string, opts ...lock.AcquireOption) error { 32 var options lock.AcquireOptions 33 for _, o := range opts { 34 o(&options) 35 } 36 37 // make path 38 path := path.Join(e.path, strings.Replace(e.opts.Prefix+id, "/", "-", -1)) 39 40 var sopts []cc.SessionOption 41 if options.TTL > 0 { 42 sopts = append(sopts, cc.WithTTL(int(options.TTL.Seconds()))) 43 } 44 45 s, err := cc.NewSession(e.client, sopts...) 46 if err != nil { 47 return err 48 } 49 50 m := cc.NewMutex(s, path) 51 52 if err := m.Lock(context.TODO()); err != nil { 53 return err 54 } 55 56 e.Lock() 57 e.locks[id] = &elock{ 58 s: s, 59 m: m, 60 } 61 e.Unlock() 62 return nil 63 } 64 65 func (e *etcdLock) Release(id string) error { 66 e.Lock() 67 defer e.Unlock() 68 v, ok := e.locks[id] 69 if !ok { 70 return errors.New("lock not found") 71 } 72 err := v.m.Unlock(context.Background()) 73 delete(e.locks, id) 74 return err 75 } 76 77 func (e *etcdLock) String() string { 78 return "etcd" 79 } 80 81 func NewLock(opts ...lock.Option) lock.Lock { 82 var options lock.Options 83 for _, o := range opts { 84 o(&options) 85 } 86 87 var endpoints []string 88 89 for _, addr := range options.Nodes { 90 if len(addr) > 0 { 91 endpoints = append(endpoints, addr) 92 } 93 } 94 95 if len(endpoints) == 0 { 96 endpoints = []string{"http://127.0.0.1:2379"} 97 } 98 99 // TODO: parse addresses 100 c, err := client.New(client.Config{ 101 Endpoints: endpoints, 102 }) 103 if err != nil { 104 log.Fatal(err) 105 } 106 107 return &etcdLock{ 108 path: "/micro/lock", 109 client: c, 110 opts: options, 111 locks: make(map[string]*elock), 112 } 113 }