Keep what discovery heard when a round hears nothing, and fetch only changed announcements (issue 554)
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

A round in which no PING reached the laptop's console within the 750 ms window
was taken as the mesh's answer that nothing is there, and replaced the index:
every seat and module call was refused for five seconds at a time. Discovery
now waits up to its patience for a first PING, a round that heard nothing is
not kept, a runtime not heard this round is resolved from what it announced
last (said with its age), and a round that misses runtimes is logged once.
A PING carries a digest of what the instance serves, so an unchanged
announcement is not pulled again every round (some 880 kB to the laptop).
This commit is contained in:
jochen
2026-10-12 13:56:50 +02:00
parent 09c5f809cb
commit 424a7eec82
11 changed files with 678 additions and 45 deletions
+19 -7
View File
@@ -775,6 +775,21 @@ type Arrival struct {
// that said it is there, not for a fixed moment (2026-10-05). Answers beyond what the caller has
// taken are kept up to the channel's room; an empty answer is no answer.
func (c *Conn) Collect(subject string, body []byte) (<-chan Arrival, func(), error) {
out, ask, stop, err := c.Collector(subject)
if err != nil {
return nil, func() {}, err
}
if err := ask(subject, body); err != nil {
stop()
return nil, func() {}, err
}
return out, stop, nil
}
// Collector is one inbox for many requests: every answer to every request `ask` publishes arrives on
// the one channel, until stopped — for discovery, which asks each service that said it is there for
// what it serves, as each says so (novox/hq issue 554). `what` names the requests in a log line.
func (c *Conn) Collector(what string) (<-chan Arrival, func(subject string, body []byte) error, func(), error) {
inbox := c.nc.NewRespInbox()
out := make(chan Arrival, 1024)
var mu sync.Mutex
@@ -792,11 +807,11 @@ func (c *Conn) Collect(subject string, body []byte) (<-chan Arrival, func(), err
select {
case out <- a:
default:
c.Logf("[mesh-tools] more answers to %s than are kept; one (%d bytes) dropped", subject, len(msg.Data))
c.Logf("[mesh-tools] more answers to %s than are kept; one (%d bytes) dropped", what, len(msg.Data))
}
})
if err != nil {
return nil, func() {}, err
return nil, nil, func() {}, err
}
stop := func() {
_ = sub.Unsubscribe()
@@ -804,11 +819,8 @@ func (c *Conn) Collect(subject string, body []byte) (<-chan Arrival, func(), err
stopped = true
mu.Unlock()
}
if err := c.nc.PublishRequest(subject, inbox, body); err != nil {
stop()
return nil, func() {}, err
}
return out, stop, nil
ask := func(subject string, body []byte) error { return c.nc.PublishRequest(subject, inbox, body) }
return out, ask, stop, nil
}
// MaxPayload is the largest message the bus carries, as the server told this connection.