node-tools: say whose words a refused event is (hq issue 276)

"plex did not take radarr.download.completed: Unexpected end of JSON input"
read as the runtime failing to parse the bundle's answer. It was plex's own
handler error, relayed. A bundle's error answer is now a launch.Refused, and
the line says the handler answered an error, quotes it, names the event id
and the delay before the next offer; the runtime's own failures (no answer
in time, bundle exited) are said as before.

The rule, unchanged and now tested: any mesh/event answer that is not an
error takes the event, whatever its result says, including none.
This commit is contained in:
jochen
2026-10-06 18:14:50 +02:00
parent f75780f1d0
commit 1792b0d9ba
4 changed files with 142 additions and 2 deletions
+23 -1
View File
@@ -7,6 +7,7 @@ package runtime
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
@@ -565,7 +566,8 @@ func (b *moduleBus) Subscribe(deliver func(json.RawMessage) error) error {
c.mu.Unlock()
for _, d := range targets {
if err := (*d)(raw); err != nil {
c.logf("[mesh-tools] %s did not take %s: %v; offered again", module, env.Key, err)
c.logf("[mesh-tools] %s did not take %s%s: %s; offered again in %s", module, env.Key,
eventRef(env), whyNotTaken(err), bus.NakDelay)
return err
}
}
@@ -579,6 +581,26 @@ func (b *moduleBus) Subscribe(deliver func(json.RawMessage) error) error {
return nil
}
// whyNotTaken says why a bundle did not take an event, so the line names who failed: the module's
// handler, in its own words — an error it answered — or the runtime not reaching it. A bundle's
// handler error read bare ("Unexpected end of JSON input") looked like the runtime's (issue 276).
func whyNotTaken(err error) string {
var refused *launch.Refused
if errors.As(err, &refused) {
return fmt.Sprintf("its handler answered an error, in its own words: %q (an event is taken by any answer that is not an error)", refused.Message)
}
return err.Error()
}
// eventRef names the event a line is about by its id, when it has one, so its offers can be told
// apart from another event's.
func eventRef(env bus.Envelope) string {
if id := env.Headers["x-event-id"]; id != "" {
return " (event " + id + ")"
}
return ""
}
// stateAsked is what a bundle names when it reaches its state (ADR 0201): the state by the name its
// module uses, a key, and for a put the value.
type stateAsked struct {