add health check to ensure default subnet is bootstrapped. add monotonicHealthCheck type

This commit is contained in:
Dan Laine 2020-06-30 14:31:30 -04:00
parent efaf2f147a
commit 1be948f38c
3 changed files with 52 additions and 0 deletions

View File

@ -63,6 +63,24 @@ func (c check) InitialDelay() time.Duration { return c.initialDelay }
// InitiallyPassing is whether or not to consider the Check healthy before the initial execution
func (c check) InitiallyPassing() bool { return c.initiallyPassing }
// monotonicCheck is a check that will run until it passes once, and after that it will
// always pass without performing any logic. Used for bootstrapping, for example.
type monotonicCheck struct {
passed bool
check
}
func (mc monotonicCheck) Execute() (interface{}, error) {
if mc.passed {
return nil, nil
}
details, pass := mc.Execute()
if pass == nil {
mc.passed = true
}
return details, pass
}
// Heartbeater provides a getter to the most recently observed heartbeat
type Heartbeater interface {
GetHeartbeat() int64

View File

@ -66,6 +66,15 @@ func (h *Health) RegisterCheckFunc(name string, checkFn CheckFn) error {
return h.RegisterCheck(check)
}
// RegisterMonotonicCheckFunc adds a Check with default options and the given CheckFn
// After it passes once, its logic (checkFunc) is never run again; it just passes
func (h *Health) RegisterMonotonicCheckFunc(name string, checkFn CheckFn) error {
check := monotonicCheck{check: defaultCheckOpts}
check.name = name
check.checkFn = checkFn
return h.RegisterCheck(check)
}
// RegisterCheck adds the given Check
func (h *Health) RegisterCheck(c Check) error {
return h.health.RegisterCheck(&health.Config{

View File

@ -7,6 +7,7 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"net"
@ -507,6 +508,30 @@ func (n *Node) initHealthAPI() error {
n.Log.Info("initializing Health API")
service := health.NewService(n.Log)
service.RegisterHeartbeat("network.validators.heartbeat", n.Net, 5*time.Minute)
isBootstrappedFunc := func() (interface{}, error) {
pChainID, err := n.chainManager.Lookup("P")
if err != nil {
return nil, errors.New("P-Chain not created")
} else if !n.chainManager.IsBootstrapped(pChainID) {
return nil, errors.New("P-Chain not bootstrapped")
}
xChainID, err := n.chainManager.Lookup("X")
if err != nil {
return nil, errors.New("X-Chain not created")
} else if !n.chainManager.IsBootstrapped(xChainID) {
return nil, errors.New("X-Chain not bootstrapped")
}
cChainID, err := n.chainManager.Lookup("C")
if err != nil {
return nil, errors.New("C-Chain not created")
} else if !n.chainManager.IsBootstrapped(cChainID) {
return nil, errors.New("C-Chain not bootstrapped")
}
return nil, nil
}
if err := service.RegisterMonotonicCheckFunc("defaultChainsBootstrapped", isBootstrappedFunc); err != nil {
return err
}
return n.APIServer.AddRoute(service.Handler(), &sync.RWMutex{}, "health", "", n.HTTPLog)
}