gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/registry/etcd/watcher.go (about) 1 package etcd 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "github.com/coreos/etcd/clientv3" 9 "gitee.com/liuxuezhan/go-micro-v1.18.0/registry" 10 ) 11 12 type etcdWatcher struct { 13 stop chan bool 14 w clientv3.WatchChan 15 client *clientv3.Client 16 timeout time.Duration 17 } 18 19 func newEtcdWatcher(r *etcdRegistry, timeout time.Duration, opts ...registry.WatchOption) (registry.Watcher, error) { 20 var wo registry.WatchOptions 21 for _, o := range opts { 22 o(&wo) 23 } 24 25 ctx, cancel := context.WithCancel(context.Background()) 26 stop := make(chan bool, 1) 27 28 go func() { 29 <-stop 30 cancel() 31 }() 32 33 watchPath := prefix 34 if len(wo.Service) > 0 { 35 watchPath = servicePath(wo.Service) + "/" 36 } 37 38 return &etcdWatcher{ 39 stop: stop, 40 w: r.client.Watch(ctx, watchPath, clientv3.WithPrefix(), clientv3.WithPrevKV()), 41 client: r.client, 42 timeout: timeout, 43 }, nil 44 } 45 46 func (ew *etcdWatcher) Next() (*registry.Result, error) { 47 for wresp := range ew.w { 48 if wresp.Err() != nil { 49 return nil, wresp.Err() 50 } 51 for _, ev := range wresp.Events { 52 service := decode(ev.Kv.Value) 53 var action string 54 55 switch ev.Type { 56 case clientv3.EventTypePut: 57 if ev.IsCreate() { 58 action = "create" 59 } else if ev.IsModify() { 60 action = "update" 61 } 62 case clientv3.EventTypeDelete: 63 action = "delete" 64 65 // get service from prevKv 66 service = decode(ev.PrevKv.Value) 67 } 68 69 if service == nil { 70 continue 71 } 72 return ®istry.Result{ 73 Action: action, 74 Service: service, 75 }, nil 76 } 77 } 78 return nil, errors.New("could not get next") 79 } 80 81 func (ew *etcdWatcher) Stop() { 82 select { 83 case <-ew.stop: 84 return 85 default: 86 close(ew.stop) 87 } 88 }