diff --git a/internal/apply/process.go b/internal/apply/process.go index 80c386e..121b683 100644 --- a/internal/apply/process.go +++ b/internal/apply/process.go @@ -536,7 +536,7 @@ func witnessOf(r *declaration.Process) string { if r.Witness != "" { return r.Witness } - return witness.Default(r.Name) + return witness.Default(r.ID, r.Name) } // digestWritten is the bundle digest a process's record says was placed: the first half of what it diff --git a/internal/witness/contract.go b/internal/witness/contract.go index 35e8b0b..9c1c6e6 100644 --- a/internal/witness/contract.go +++ b/internal/witness/contract.go @@ -9,6 +9,7 @@ package witness import ( "time" + "github.com/novox/mesh-host/internal/compose/resolution" "github.com/novox/mesh-host/internal/link" ) @@ -33,15 +34,13 @@ const ( GiveUp = 30 * time.Minute ) -// NodeToolsService is the runtime's name on the services protocol, and its instance is this -// machine's node name: what `$SRV.PING..` asks, so only this machine's runtime can -// answer (mesh-tools node-tools internal/runtime, announce.Service{Name: module, ID: node}). -const NodeToolsService = "node-tools" - -// Default is the witness a process is judged by when it names none: the core process the mesh composes on every -// machine, by the name it composes it under, and nothing else. -func Default(process string) string { - if process == NodeToolsService { +// Default is the witness a process is judged by when it names none: the tool runner's process, the core process the mesh +// composes on every machine for the module whose manifest says it is the tool runner (catalogue.IsToolRunner), with the id +// `.runtime` and named as its module (resolution's runtime process), and nothing else. It is pinged by that +// name on this machine's instance, `$SRV.PING..`, so only this machine's runtime answers; never known here by +// a module's name (ADR 0601 §4). +func Default(id, process string) string { + if process != "" && id == process+"."+resolution.RuntimeProcessID() { return ByPing } return ByNone diff --git a/internal/witness/contract_test.go b/internal/witness/contract_test.go index 2ea5c5c..6677fe9 100644 --- a/internal/witness/contract_test.go +++ b/internal/witness/contract_test.go @@ -13,7 +13,7 @@ import ( // The runtime is asked by its own name and this machine's: only this machine's runtime can answer. func TestTheRuntimeIsAskedByItsNameAndThisMachines(t *testing.T) { - if got := link.PingSubject(NodeToolsService, "anchor"); got != "$SRV.PING.node-tools.anchor" { + if got := link.PingSubject("runner-x", "anchor"); got != "$SRV.PING.runner-x.anchor" { t.Fatalf("the host asks %s; the runtime answers $SRV.PING.node-tools.", got) } } @@ -21,9 +21,12 @@ func TestTheRuntimeIsAskedByItsNameAndThisMachines(t *testing.T) { // What is judged by default is the mesh's core process on every machine, by the name it is composed under, and // nothing else: the controller ended (issue 1126), so its name is judged as any other. func TestOnlyTheCoreProcessIsJudgedByDefault(t *testing.T) { - for name, want := range map[string]string{"mesh-controller": ByNone, "node-tools": ByPing, "greeter": ByNone} { - if got := Default(name); got != want { - t.Errorf("%s is judged by %q, want %q", name, got, want) + // The tool runner's process by its id and name, whatever its module is called (ADR 0601 §4); a process named so by + // another id, or another process, is not. + for id, want := range map[string]string{"runner-x.runtime": ByPing, "node-tools.runtime": ByNone, "runner-x.server": ByNone, + "mesh-controller.runtime": ByNone} { + if got := Default(id, "runner-x"); got != want { + t.Errorf("%s is judged by %q, want %q", id, got, want) } } if NodeToolsWithin != 60*time.Second || PingWithin != 5*time.Second {