Read memberships from the grants part's state, what the mesh holds from the indexer and placement, and give bundles newest, since and watch on logs, so the tool runner asks the controller for nothing it keeps (issue 1955, ADR 0571 clauses 1, 4, 5, 7)

Pins mesh-sdk bb993dd. The assignments stream stays the membership's
fallback until the lease write; a log another module keeps is read as
<module>.<log>.
This commit is contained in:
2026-10-29 23:42:43 +01:00
parent 200249a84f
commit 54680238a0
16 changed files with 716 additions and 204 deletions
+11 -11
View File
@@ -56,6 +56,10 @@ func TestARuntimeThatAnswersLateIsFoundAndOneThatNeverDoesIsNamed(t *testing.T)
IndexKept, announce.Patience = time.Minute, 2500*time.Millisecond
t.Cleanup(func() { IndexKept, announce.Patience = keptWas, patienceWas })
mesh := mt.New(t)
// What the mesh holds, as the indexer and placement write it (ADR 0571): never the controller's records.
mesh.Placed(t, map[string][]string{"slack": {"slack_check"}, "nap": {"doze"}, "nextcloud-client": {"nextcloud_check"}},
map[string][]string{"laptop": {"slack", "nextcloud-client"}, "sleeper": {"nap", "nextcloud-client"},
"desktop": {"nextcloud-client"}, "bench": nil})
// Who holds which seat, by placement (ADR 0571 clause 4), as the seat mesh-placement's holder composes it.
placedKV := mesh.Bucket(t, delivery.SeatHoldersBucket)
for key, sh := range delivery.SeatHoldersOf(map[string]delivery.Placement{"bench": {Node: "bench",
@@ -66,7 +70,7 @@ func TestARuntimeThatAnswersLateIsFoundAndOneThatNeverDoesIsNamed(t *testing.T)
}
}
consoleMembership := mt.MembershipOf("node-tools", "laptop-console", false, nil)
consoleMembership.State = []bus.StateIssued{{Name: delivery.SeatHoldersRead, Bucket: delivery.SeatHoldersBucket}}
consoleMembership.State = mt.ConsoleReads()
mesh.Issue(t, consoleMembership)
laptop := connect(t, "node-tools", "laptop")
@@ -94,18 +98,14 @@ func TestARuntimeThatAnswersLateIsFoundAndOneThatNeverDoesIsNamed(t *testing.T)
controller := connect(t, "mesh-controller", "bench")
var toolsAsked atomic.Int32
for verb, output := range map[string]string{
"nodes": `[{"name":"laptop"},{"name":"sleeper"},{"name":"desktop"},{"name":"bench"}]`,
"modules": `[{"module":"slack","on":["laptop"],"tools":true},{"module":"nap","on":["sleeper"],"tools":true},` +
`{"module":"nextcloud-client","on":["laptop","desktop","sleeper"],"tools":true}]`,
// No part keeps a central record of tools (ADR 0571 clause 5): a seat verb's `replaces` is read from its contract
// in mesh-sdk, so the controller's `tools` is served here only to see that it is never asked.
"tools": `{"seats":[]}`,
// The controller's records are served here only to see that none is asked (ADR 0571 clauses 4 and 5).
"nodes": `[{"name":"laptop"}]`,
"modules": `[]`,
"tools": `{"seats":[]}`,
} {
output, verb := output, verb
stop, err := controller.HandleSubject("mesh.seat.mesh-controller.tool."+verb, func(json.RawMessage) (any, error) {
if verb == "tools" {
toolsAsked.Add(1)
}
toolsAsked.Add(1)
return map[string]any{"output": output, "ok": true}, nil
})
if err != nil {
@@ -149,7 +149,7 @@ func TestARuntimeThatAnswersLateIsFoundAndOneThatNeverDoesIsNamed(t *testing.T)
t.Errorf("mesh/seats answered %s", raw)
}
if n := toolsAsked.Load(); n != 0 {
t.Errorf("the console asked the controller's tools %d times", n)
t.Errorf("the console asked the controller's records %d times", n)
}
// The silent one is named, never called missing.