c40779224f
Fixes #52
73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package etcd
|
|
|
|
import (
|
|
"github.com/go-kit/kit/endpoint"
|
|
"github.com/go-kit/kit/log"
|
|
"github.com/go-kit/kit/sd"
|
|
"github.com/go-kit/kit/sd/cache"
|
|
)
|
|
|
|
// Subscriber yield endpoints stored in a certain etcd keyspace. Any kind of
|
|
// change in that keyspace is watched and will update the Subscriber endpoints.
|
|
type Subscriber struct {
|
|
client Client
|
|
prefix string
|
|
cache *cache.Cache
|
|
logger log.Logger
|
|
quitc chan struct{}
|
|
}
|
|
|
|
var _ sd.Subscriber = &Subscriber{}
|
|
|
|
// NewSubscriber returns an etcd subscriber. It will start watching the given
|
|
// prefix for changes, and update the endpoints.
|
|
func NewSubscriber(c Client, prefix string, factory sd.Factory, logger log.Logger) (*Subscriber, error) {
|
|
s := &Subscriber{
|
|
client: c,
|
|
prefix: prefix,
|
|
cache: cache.New(factory, logger),
|
|
logger: logger,
|
|
quitc: make(chan struct{}),
|
|
}
|
|
|
|
instances, err := s.client.GetEntries(s.prefix)
|
|
if err == nil {
|
|
logger.Log("prefix", s.prefix, "instances", len(instances))
|
|
} else {
|
|
logger.Log("prefix", s.prefix, "err", err)
|
|
}
|
|
s.cache.Update(instances)
|
|
|
|
go s.loop()
|
|
return s, nil
|
|
}
|
|
|
|
func (s *Subscriber) loop() {
|
|
ch := make(chan struct{})
|
|
go s.client.WatchPrefix(s.prefix, ch)
|
|
for {
|
|
select {
|
|
case <-ch:
|
|
instances, err := s.client.GetEntries(s.prefix)
|
|
if err != nil {
|
|
s.logger.Log("msg", "failed to retrieve entries", "err", err)
|
|
continue
|
|
}
|
|
s.cache.Update(instances)
|
|
|
|
case <-s.quitc:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// Endpoints implements the Subscriber interface.
|
|
func (s *Subscriber) Endpoints() ([]endpoint.Endpoint, error) {
|
|
return s.cache.Endpoints(), nil
|
|
}
|
|
|
|
// Stop terminates the Subscriber.
|
|
func (s *Subscriber) Stop() {
|
|
close(s.quitc)
|
|
}
|