Answer dead-letters on the lent serving connection, and keep one clip helper
mesh/delivery delivered
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check pass: its merge-check.sh passed

Two handles to the same serving connection, and two copies of one helper,
would drift (review of hq issues 327 and 330).
This commit is contained in:
jochen
2026-10-08 21:09:08 +02:00
parent cc7fb99f29
commit 5b7e6ff453
5 changed files with 9 additions and 27 deletions
+3 -7
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"strconv"
"strings"
"sync/atomic"
"github.com/nats-io/nats.go"
@@ -22,10 +21,6 @@ import (
// serving controller is already on it. A verb run as a fresh process would open a connection of its own
// for each call (novox/hq issue 327).
// deadLettersOn is the serving controller's bus, set when it starts watching the mesh; nil in a
// process that serves nothing.
var deadLettersOn atomic.Pointer[busHandles]
// busHandles are the serving controller's connection and JetStream handle.
type busHandles struct {
conn *nats.Conn
@@ -41,11 +36,12 @@ const causeDeadLetter = "dead-letter"
// deadLettersAnswer is what `dead-letters` answers: the list, one whole, or what came of delivering one
// again or dropping it.
func deadLettersAnswer(ctx context.Context, a *verbArguments) (any, error) {
on := deadLettersOn.Load()
if on == nil {
serving := servingBus.Load()
if serving == nil {
return nil, errors.New("this controller is not serving, so it does not read DEAD_LETTERS: ask again, " +
"and the serving controller answers")
}
on := &busHandles{conn: serving.Conn(), js: serving.Context()}
// The shape first, and every argument it reads; one given beside it is refused before anything is
// done, as every verb refuses what it would pass over (novox/hq issue 244).
var deliver, drop, why, cause, idText, consumer, limit string