github.com/xmidt-org/webpa-common@v1.11.9/service/zk/environment.go (about) 1 package zk 2 3 import ( 4 "github.com/go-kit/kit/log" 5 "github.com/go-kit/kit/log/level" 6 "github.com/go-kit/kit/sd" 7 gokitzk "github.com/go-kit/kit/sd/zk" 8 "github.com/xmidt-org/webpa-common/logging" 9 "github.com/xmidt-org/webpa-common/service" 10 ) 11 12 func newService(r Registration) (string, gokitzk.Service) { 13 url := service.FormatInstance( 14 r.scheme(), 15 r.address(), 16 r.port(), 17 ) 18 19 return url, gokitzk.Service{ 20 Path: r.path(), 21 Name: r.name(), 22 Data: []byte(url), 23 } 24 } 25 26 // clientFactory is the factory function used to create a go-kit zookeeper Client. 27 // Tests can change this for mocked behavior. 28 var clientFactory = gokitzk.NewClient 29 30 func newClient(l log.Logger, zo Options) (gokitzk.Client, error) { 31 client := zo.client() 32 return clientFactory( 33 client.servers(), 34 l, 35 gokitzk.ConnectTimeout(client.connectTimeout()), 36 gokitzk.SessionTimeout(client.sessionTimeout()), 37 ) 38 } 39 40 func newInstancer(l log.Logger, c gokitzk.Client, path string) (i sd.Instancer, err error) { 41 i, err = gokitzk.NewInstancer(c, path, l) 42 if err == nil { 43 i = service.NewContextualInstancer(i, map[string]interface{}{"path": path}) 44 } 45 46 return 47 } 48 49 func newInstancers(l log.Logger, c gokitzk.Client, zo Options) (i service.Instancers, err error) { 50 for _, path := range zo.watches() { 51 if i.Has(path) { 52 l.Log(level.Key(), level.WarnValue(), logging.MessageKey(), "skipping duplicate watch", "path", path) 53 continue 54 } 55 56 var instancer sd.Instancer 57 instancer, err = newInstancer(l, c, path) 58 if err != nil { 59 // ensure the previously create instancers are stopped 60 i.Stop() 61 return 62 } 63 64 i.Set(path, instancer) 65 } 66 67 return 68 } 69 70 func newRegistrars(base log.Logger, c gokitzk.Client, zo Options) (r service.Registrars) { 71 for _, registration := range zo.registrations() { 72 instance, s := newService(registration) 73 if r.Has(instance) { 74 base.Log(level.Key(), level.WarnValue(), logging.MessageKey(), "skipping duplicate registration", "instance", instance) 75 continue 76 } 77 78 r.Add(instance, gokitzk.NewRegistrar(c, s, log.With(base, "instance", instance))) 79 } 80 81 return 82 } 83 84 // NewEnvironment constructs a Zookeeper-based service.Environment using both a zookeeper Options (typically unmarshaled 85 // from configuration) and an optional extra set of environment options. 86 func NewEnvironment(l log.Logger, zo Options, eo ...service.Option) (service.Environment, error) { 87 if l == nil { 88 l = logging.DefaultLogger() 89 } 90 91 if len(zo.Watches) == 0 && len(zo.Registrations) == 0 { 92 return nil, service.ErrIncomplete 93 } 94 95 c, err := newClient(l, zo) 96 if err != nil { 97 return nil, err 98 } 99 100 i, err := newInstancers(l, c, zo) 101 if err != nil { 102 c.Stop() 103 return nil, err 104 } 105 106 return service.NewEnvironment( 107 append( 108 eo, 109 service.WithRegistrars(newRegistrars(l, c, zo)), 110 service.WithInstancers(i), 111 service.WithCloser(func() error { c.Stop(); return nil }), 112 )..., 113 ), nil 114 }