Every module follows the assigner's new places: the contracts' go/ path, mesh-wants in the delivery contracts, the state and tool assignments (issue 1966)

The legacy key form placement.<node> is gone from the client, so the readers and their fixtures lose it. The check noplacement
now also refuses the assigner's retired names in a manifest.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 22:29:07 +01:00
parent 2dc9e07e88
commit c9d8950fd0
109 changed files with 682 additions and 681 deletions
+12 -12
View File
@@ -10,8 +10,8 @@ import (
"context"
"encoding/json"
"fmt"
assignerclient "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
mesh "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
assignerclient "git.novox.be/novox/mesh-contracts/go/clients/meshmoduleassignerclient"
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
"os"
"strings"
"sync"
@@ -76,10 +76,10 @@ func main() {
node := os.Getenv("MESH_NODE")
w := NewWatcher(tg, time.Now, logf, node)
l := &listening{now: "not yet: starting"}
placement := &views.Reader{Module: "mesh-watcher", Logf: logf, Findings: meshconditionsclient.FindingWriter{State: stdio.State("findings")}, Acts: meshhandactsclient.Recorder{Ask: stdio.Ask}}
placement.Follow(assignerModule, mesh.StateSeatHolders, SeatHoldersTool)
go run(w, l, node, placement)
if err := stdio.Serve("", append(tools(w, l), placement.Tools("watcher")...)); err != nil {
assignments := &views.Reader{Module: "mesh-watcher", Logf: logf, Findings: meshconditionsclient.FindingWriter{State: stdio.State("findings")}, Acts: meshhandactsclient.Recorder{Ask: stdio.Ask}}
assignments.Follow(assignerModule, mesh.StateSeatHolders, SeatHoldersTool)
go run(w, l, node, assignments)
if err := stdio.Serve("", append(tools(w, l), assignments.Tools("watcher")...)); err != nil {
logf("%v", err)
os.Exit(1)
}
@@ -87,7 +87,7 @@ func main() {
// run keeps time, makes the round trips, reads where the controller is, and listens for heartbeats.
// The clock runs whatever the bus does: it is what notices the bus is gone.
func run(w *Watcher, l *listening, node string, placement *views.Reader) {
func run(w *Watcher, l *listening, node string, assignments *views.Reader) {
if err := w.Telegram.Ready(); err != nil {
logf("[mesh-watcher] BLIND until given: %v", err)
}
@@ -100,14 +100,14 @@ func run(w *Watcher, l *listening, node string, placement *views.Reader) {
// Where the bus runs: the assigner's seat-holders, asked once and then followed by its events (ADR 0615), never read
// from its state and never on a timer.
placed := func() {
if nodes, err := controlNodes(placement); err == nil {
if nodes, err := controlNodes(assignments); err == nil {
w.Placed(nodes)
} else {
logf("[mesh-watcher] cannot read where the bus runs (%v)", err)
}
}
placement.Changed = func(string, string, json.RawMessage, bool) { placed() }
placement.Start(context.Background())
assignments.Changed = func(string, string, json.RawMessage, bool) { placed() }
assignments.Start(context.Background())
handle := func(e stdio.Envelope) error {
if !isHeartbeat(e.Key) {
return nil
@@ -162,7 +162,7 @@ const assignerModule = "mesh-delivery-assigner"
const SeatHoldersTool = assignerModule + ".assigner_read_seat_holders"
// controlNodes reads which machines hold the bus, from the placement seat's state of who holds which seat (novox/hq
// controlNodes reads which machines hold the bus, from the assignments seat's state of who holds which seat (novox/hq
// ADR 0571 clause 4). The controller is not placed (ADR 0590), so the bus's machines are the control node.
func controlNodes(seats *views.Reader) ([]string, error) {
keys, err := seats.Values(assignerModule + "." + mesh.StateSeatHolders)
@@ -189,7 +189,7 @@ func holderNodes(keys map[string][]byte, seats ...string) ([]string, error) {
}
}
if len(out) == 0 {
return nil, fmt.Errorf("the placement seat's state names no holder of %s", strings.Join(seats, " or "))
return nil, fmt.Errorf("the assignments seat's state names no holder of %s", strings.Join(seats, " or "))
}
return out, nil
}
@@ -2,7 +2,7 @@ package main
import (
"encoding/json"
mesh "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
"os"
"path/filepath"
"reflect"
@@ -213,7 +213,7 @@ func TestOnTheControlNodeItSaysItIsMisplaced(t *testing.T) {
}
}
func TestTheHoldersAreReadFromThePlacementSeatsState(t *testing.T) {
func TestTheHoldersAreReadFromTheAssignmentsSeatsState(t *testing.T) {
keys := map[string][]byte{
"mesh-broker": []byte(`{"v":1,"seat":"mesh-broker","scope":"mesh","holders":[{"module":"nats","node":"n1"},{"module":"nats","node":"n2"},{"module":"nats","node":"n1"}]}`),
"git": []byte(`{"v":1,"seat":"git","scope":"mesh","holders":[{"module":"gitea","node":"n3"}]}`),