Keep a machine's discovery answer under the bus's message limit
Every tool's schema in one $SRV.INFO reply outgrew max_payload on machines serving 137-206 tools, and the refused reply was dropped silently, so search and a machine's view went empty. Module tools now announce without schema; describe and tools/list ask the module for it. An answer still too large has its descriptions cut to a line, and a failed reply is logged.
This commit is contained in:
@@ -74,11 +74,19 @@ func (e Endpoint) info() micro.EndpointInfo {
|
||||
"kind": e.Kind, "module": e.Module, "tool": e.Tool, "node": e.Node,
|
||||
"description": e.Description, "interchangeable": boolWord(e.Interchangeable),
|
||||
}
|
||||
schema := strings.TrimSpace(string(e.Schema))
|
||||
if schema == "" || schema == "null" {
|
||||
schema = "{}"
|
||||
// **A seat's verb carries its schema; a module's tool does not.** Every tool's schema, once per
|
||||
// subject it answers on, made a runtime's one answer outgrow the bus's largest message (1 MiB) once
|
||||
// machines served a couple of hundred tools — and the answer that cannot be sent is silence: the
|
||||
// machine vanished from discovery (2026-10-04). A module's tool's schema is asked of the runtime that
|
||||
// serves it when a person describes it (its `tools` verb); a seat's verbs are few, and a seat has no
|
||||
// `tools` verb of its own to ask.
|
||||
if e.Kind == KindSeat {
|
||||
schema := strings.TrimSpace(string(e.Schema))
|
||||
if schema == "" || schema == "null" {
|
||||
schema = "{}"
|
||||
}
|
||||
md["schema"] = schema
|
||||
}
|
||||
md["schema"] = schema
|
||||
if e.Kind == KindSeat {
|
||||
md["seat"] = e.Seat
|
||||
md["scope"] = e.Scope
|
||||
@@ -154,6 +162,20 @@ func Serve(conn *bus.Conn, s Service, current func() []Endpoint) (func(), error)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
// Too large for the bus is no answer at all, and was silent: shorten every description to its
|
||||
// first line and say so, rather than vanish.
|
||||
if limit := conn.MaxPayload(); limit > 0 && int64(len(body)) > limit {
|
||||
if info, ok := v.(micro.Info); ok {
|
||||
for i := range info.Endpoints {
|
||||
info.Endpoints[i].Metadata["description"] = firstLine(info.Endpoints[i].Metadata["description"])
|
||||
}
|
||||
if shorter, err := json.Marshal(info); err == nil {
|
||||
conn.Logf("[mesh-tools] what this runtime serves is %d bytes, beyond the bus's %d; announced with each description cut to its first line (%d bytes)",
|
||||
len(body), limit, len(shorter))
|
||||
body = shorter
|
||||
}
|
||||
}
|
||||
}
|
||||
return body
|
||||
}
|
||||
var stops []func()
|
||||
@@ -209,3 +231,17 @@ func Endpoints(i micro.Info) []Endpoint {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// firstLine is a description's first sentence or line, at most 160 characters.
|
||||
func firstLine(s string) string {
|
||||
if i := strings.IndexAny(s, "\n"); i >= 0 {
|
||||
s = s[:i]
|
||||
}
|
||||
if i := strings.Index(s, ". "); i >= 0 {
|
||||
s = s[:i+1]
|
||||
}
|
||||
if len(s) > 160 {
|
||||
s = s[:157] + "..."
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user