Say the node tools are there, every minute (hq to-be 45 Phase 1, S11)
A machine whose node-engine is heard and whose runtime is gone is a machine nobody can ask anything, and nothing said so. The runtime now says on mesh.control.<node>.tools-alive, every minute, that it is there, with its interval and build; the controller raises tools-silent after three missed. Core NATS, like the host's heartbeat: a lost one is the next one. A heartbeat the bus refuses is logged when that starts and when it stops.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package alive
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type said struct {
|
||||
mu sync.Mutex
|
||||
subs []string
|
||||
body [][]byte
|
||||
fail error
|
||||
}
|
||||
|
||||
func (s *said) Say(subject string, body []byte) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.fail != nil {
|
||||
return s.fail
|
||||
}
|
||||
s.subs, s.body = append(s.subs, subject), append(s.body, body)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *said) count() int {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return len(s.subs)
|
||||
}
|
||||
|
||||
// **The runtime says it is there at once and every interval, as its machine, with the interval**: the
|
||||
// controller's bound is three of them (to-be 45 S11).
|
||||
func TestTheRuntimeSaysItIsThereEveryInterval(t *testing.T) {
|
||||
s := &said{}
|
||||
stop := Keep(s, "anchor", 20*time.Millisecond, t.Logf)
|
||||
time.Sleep(70 * time.Millisecond)
|
||||
stop()
|
||||
stop()
|
||||
if n := s.count(); n < 3 {
|
||||
t.Fatalf("said %d times in three intervals", n)
|
||||
}
|
||||
var beat Beat
|
||||
if err := json.Unmarshal(s.body[0], &beat); err != nil || beat.Node != "anchor" || beat.IntervalSeconds != 0 ||
|
||||
s.subs[0] != "mesh.control.anchor.tools-alive" {
|
||||
t.Fatalf("%s on %s: %v", s.body[0], s.subs[0], err)
|
||||
}
|
||||
n := s.count()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
if s.count() != n {
|
||||
t.Fatal("said after it was stopped")
|
||||
}
|
||||
}
|
||||
|
||||
// **A heartbeat the bus will not take is said once, and again when it is taken**: not a line a minute.
|
||||
func TestAHeartbeatThatCannotBeSaidIsLoggedOnce(t *testing.T) {
|
||||
s := &said{fail: errors.New("permissions violation")}
|
||||
var mu sync.Mutex
|
||||
var lines []string
|
||||
stop := Keep(s, "anchor", 10*time.Millisecond, func(f string, a ...any) {
|
||||
mu.Lock()
|
||||
lines = append(lines, f)
|
||||
mu.Unlock()
|
||||
})
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
stop()
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if len(lines) != 1 {
|
||||
t.Fatalf("logged %d lines for one failure", len(lines))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user