Codebase list golang-github-go-kit-kit / cb03da6 sd / eureka / registrar.go
cb03da6

Tree @cb03da6 (Download .tar.gz)

registrar.go @cb03da6raw · history · blame

package eureka

import (
	"fmt"
	"sync"
	"time"

	stdeureka "github.com/hudl/fargo"

	"github.com/go-kit/kit/log"
)

// Registrar maintains service instance liveness information in Eureka.
type Registrar struct {
	client   Client
	instance *stdeureka.Instance
	logger   log.Logger

	quitmtx sync.Mutex
	quit    chan bool
}

// NewRegistrar returns an Eureka Registrar acting on behalf of the provided
// Fargo instance.
func NewRegistrar(client Client, i *stdeureka.Instance, l log.Logger) *Registrar {
	return &Registrar{
		client:   client,
		instance: i,
		logger:   log.With(l, "service", i.App, "address", fmt.Sprintf("%s:%d", i.IPAddr, i.Port)),
	}
}

// Register implements sd.Registrar interface.
func (r *Registrar) Register() {
	if err := r.client.Register(r.instance); err != nil {
		r.logger.Log("err", err)
	} else {
		r.logger.Log("action", "register")
	}

	if r.instance.LeaseInfo.RenewalIntervalInSecs > 0 {
		// User has opted for heartbeat functionality in Eureka.
		go r.loop()
	}
}

// Deregister implements sd.Registrar interface.
func (r *Registrar) Deregister() {
	if err := r.client.Deregister(r.instance); err != nil {
		r.logger.Log("err", err)
	} else {
		r.logger.Log("action", "deregister")
	}

	r.quitmtx.Lock()
	defer r.quitmtx.Unlock()
	if r.quit != nil {
		r.quit <- true
	}
}

func (r *Registrar) loop() {
	r.quitmtx.Lock()
	if r.quit != nil {
		defer r.quitmtx.Unlock()
		return // Already running.
	}
	r.quit = make(chan bool)
	r.quitmtx.Unlock()

	tick := time.NewTicker(time.Duration(r.instance.LeaseInfo.RenewalIntervalInSecs) * time.Second)
	defer tick.Stop()
	for {
		select {
		case <-tick.C:
			if err := r.client.Heartbeat(r.instance); err != nil {
				r.logger.Log("err", err)
			}
		case <-r.quit:
			r.quitmtx.Lock()
			defer r.quitmtx.Unlock()

			close(r.quit)
			r.quit = nil

			return
		}
	}
}