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.
75 lines
1.7 KiB
Go
75 lines
1.7 KiB
Go
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))
|
|
}
|
|
}
|