The tool runner reads its membership from the grants part's state alone: no stream read, no subject heard (ADR 0571 §10)
Follow no longer asks the ASSIGNMENTS stream for a copy nor subscribes mesh.assignment; a module with no membership key is said so and served in its derived shape. The test mesh issues memberships where the grants part keeps them. Tests: none added; the stream-fallback assertions of two existing tests are replaced by their state-only counterparts, and the test mesh no longer makes the stream. The two integration tests of the bus were run locally against the embedded bus. (issue 774, 774/S32) Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -161,11 +161,11 @@ func TestAModuleHearsEveryStreamItsMembershipNames(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
// The membership as the grants part keeps it (ADR 0571 clause 7): read first, applied live, and the assignments
|
||||
// stream's copy passed over once the state has given one.
|
||||
// The membership as the grants part keeps it (ADR 0571 clause 7, 10): read first and applied live, and nothing
|
||||
// published on the controller's subject is heard.
|
||||
granted := reader
|
||||
granted.Hears = []bus.HeardIssued{{Stream: "MAIL", Consumer: "from-grants"}}
|
||||
mesh.IssueInGrants(t, granted)
|
||||
mesh.Issue(t, granted)
|
||||
again, err := bus.Connect(bus.Credential{URL: mt.URL(t), Module: "node-tools", Node: "anchor"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -183,45 +183,21 @@ func TestAModuleHearsEveryStreamItsMembershipNames(t *testing.T) {
|
||||
t.Fatalf("the membership read at the follow names %q, want the grants part's", got)
|
||||
}
|
||||
granted.Hears[0].Consumer = "from-grants-2"
|
||||
mesh.IssueInGrants(t, granted)
|
||||
mesh.Issue(t, granted)
|
||||
mt.Until(t, func() error {
|
||||
if got := consumerOf(); got != "from-grants-2" {
|
||||
return fmt.Errorf("the membership names %q, want the grants part's change", got)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
// A later, different copy on the assignments stream changes nothing once the state has given one.
|
||||
arrived := make(chan struct{}, 1)
|
||||
probe, err := bus.Connect(bus.Credential{URL: mt.URL(t), Module: "probe", Node: "elsewhere"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
probe.Logf = func(string, ...any) {}
|
||||
t.Cleanup(probe.Close)
|
||||
stopProbe, err := probe.Raw(bus.MembershipSubject("anchor", "reader"), func(string, []byte) []byte {
|
||||
select {
|
||||
case arrived <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(stopProbe)
|
||||
probe.Flush()
|
||||
// 774/S32/AC1: a copy said on the controller's subject (mesh.assignment) changes nothing; there is no stream to read it from.
|
||||
streamed := reader
|
||||
streamed.Hears = []bus.HeardIssued{{Stream: "MAIL", Consumer: "from-stream"}}
|
||||
mesh.Issue(t, streamed)
|
||||
select {
|
||||
case <-arrived:
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("the stream's copy was not published")
|
||||
}
|
||||
streamed.Hears = []bus.HeardIssued{{Stream: "MAIL", Consumer: "from-subject"}}
|
||||
mesh.Publish(t, "mesh.assignment.anchor.reader", streamed)
|
||||
again.Flush()
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
if got := consumerOf(); got != "from-grants-2" {
|
||||
t.Fatalf("the stream's copy was applied over the grants part's: the membership names %q", got)
|
||||
t.Fatalf("a membership said on the controller's subject was applied: the membership names %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user