node-tools: only a call pattern names a caller, and a fall-back for want of a responder is said (hq issue 365, review)
mesh/merge-gate pass: builds mesh-tools, node-tools → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of …
mesh/repo-check pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the change's judges the pull requests after it merges; it…
mesh/delivery delivered

callerOn reads a caller only under the call kind, so a tool subscription ending
in a wildcard never yields one. A caller-named call that reached nobody is said
once per subject before it is asked on the old subject, so a runtime or grant
that drifted behind is seen rather than a quiet unproven. The caller tests wait
for their bundle's exit, which reads the launcher's restart pauses another test
sets.
This commit is contained in:
2026-10-11 11:22:29 +02:00
parent ab0f888d67
commit 541de48e04
4 changed files with 89 additions and 6 deletions
@@ -180,3 +180,39 @@ func TestAGrantedCallerIsHeardAsItselfAndCannotNameAnother(t *testing.T) {
t.Errorf("heard %v; want the asker alone, as itself", got)
}
}
// A fall-back for want of a responder on the caller-named subject is said, once per subject, so a runtime or
// grant that drifted behind is seen rather than read as a quiet "unproven".
func TestAFallBackForWantOfAResponderIsSaidOncePerSubject(t *testing.T) {
url := mt.URL(t)
// A runtime from before issue 365: the subject that names no caller, alone.
older, err := nats.Connect(url)
if err != nil {
t.Fatal(err)
}
defer older.Close()
if _, err := older.Subscribe("mesh.mod.ledger.tool.who", func(m *nats.Msg) { _ = m.Respond([]byte(`{"result":{}}`)) }); err != nil {
t.Fatal(err)
}
_ = older.Flush()
asker := dial(t, url, "node-tools", "shanks", "shanks.node-tools")
var mu sync.Mutex
var said []string
asker.Logf = func(f string, a ...any) { mu.Lock(); said = append(said, fmt.Sprintf(f, a...)); mu.Unlock() }
for i := 0; i < 3; i++ {
if _, err := asker.Ask("ledger.who", map[string]any{}, ""); err != nil {
t.Fatal(err)
}
}
mu.Lock()
defer mu.Unlock()
n := 0
for _, s := range said {
if strings.Contains(s, "nothing answers the caller-named mesh.mod.ledger.call.who.shanks~node-tools") {
n++
}
}
if n != 1 {
t.Errorf("the fall-back was said %d times, want once: %v", n, said)
}
}