The controller no longer subscribes to the alive message: HostBeats, its handler, the heartbeat-gap duration and a fixed silent bound (issue 1183, AC3, AC4, AC5)
mesh/merge-gate head 19e3eac74658 merged into trunk 89cfa9431d8f — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/repo-check head 19e3eac74658 merged into trunk 89cfa9431d8f — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/merge-gate head 19e3eac74658 merged into trunk 89cfa9431d8f — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every …
mesh/repo-check head 19e3eac74658 merged into trunk 89cfa9431d8f — pass: its merge-check.sh passed
mesh/delivery delivered
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/broker"
|
||||
"github.com/novox/mesh-controller/internal/inventory"
|
||||
"github.com/novox/mesh-controller/internal/testbus"
|
||||
)
|
||||
|
||||
// 1183/AC5: with the watchman's presence bucket holding a node online and no alive message ever sent, the node reads here
|
||||
// in `nodes` four minutes later by the controller's clock, however old its last report; and an alive message still sent
|
||||
// by a node-engine is published to the same bus without error and changes nothing.
|
||||
func TestAnOnlineNodeReadsHereWithNoAliveMessage(t *testing.T) { // 1183/AC5
|
||||
js, err := broker.Dial(testbus.URL(t))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(js.Close)
|
||||
if _, err := broker.RaiseBuckets(js, []broker.Bucket{
|
||||
{Module: sdkdelivery.WatchmanModule, Name: "presence", History: sdkdelivery.PresenceHistory},
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
api, err := jetstream.New(js.Conn())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kv, err := api.KeyValue(ctx, sdkdelivery.PresenceBucket)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
put := func(node string, online bool) {
|
||||
t.Helper()
|
||||
key, err := sdkdelivery.PresenceNodeKey(node)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body, err := sdkdelivery.EncodePresence(sdkdelivery.Presence{Online: online})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := kv.Put(ctx, key, body); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
put("ace", true)
|
||||
put("laptop", false)
|
||||
// A node-engine still sending its alive message: harmless.
|
||||
if err := js.Conn().Publish("mesh.control.ace.alive", []byte(`{"node":"ace"}`)); err != nil {
|
||||
t.Fatalf("an alive message could not be published: %v", err)
|
||||
}
|
||||
if err := js.Conn().Flush(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
later := time.Now().Add(4 * time.Minute)
|
||||
nodes := []inventory.Node{{Name: "ace", LastSeen: time.Now().Add(-time.Hour)},
|
||||
{Name: "laptop", LastSeen: time.Now().Add(-time.Hour)}}
|
||||
read := func(ctx context.Context, names []string) (map[string]presenceEntry, error) {
|
||||
return readPresence(ctx, js.Conn(), names)
|
||||
}
|
||||
heard, err := nodesHeard(ctx, nodes, read, later)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := heardFromAt(heard[0], later); got != "here" {
|
||||
t.Fatalf("a node online by presence reads %q four minutes later", got)
|
||||
}
|
||||
if got := heardFromAt(heard[1], later); got == "here" {
|
||||
t.Fatalf("a node offline by presence reads %q", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user