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  }