From 3fdbea420440a5da8af12d97ef6f7c29f8060b54 Mon Sep 17 00:00:00 2001 From: mesh-tools Date: Fri, 16 Oct 2026 00:27:57 +0000 Subject: [PATCH] =?UTF-8?q?Ask=20mesh-delivery=20for=20a=20recheck's=20gro?= =?UTF-8?q?up=20on=20a=20bus=20connection=20of=20its=20own=20(issue=20867,?= =?UTF-8?q?=20ADR=200382=20=C2=A71)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `delivery check` runs as a command of its own, where no serving connection exists, so a recheck said its siblings could not be learned ("this controller is not on the bus") and mesh-host#114 was judged without its sibling. groupsAsked now asks through onTheBus, which lends the serving connection or dials one, as the hand-act log does. TestTheRecheckVerbAsksMeshDeliveryOnABusOfItsOwn drives the verb against a real responder. Co-Authored-By: Claude --- cmd/mesh-controller/group_wait.go | 19 +++++---- cmd/mesh-controller/replay867_test.go | 55 ++++++++++++++++++++++++--- testdata/store-tests | 1 + 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/cmd/mesh-controller/group_wait.go b/cmd/mesh-controller/group_wait.go index 12cc63a3..1be26410 100644 --- a/cmd/mesh-controller/group_wait.go +++ b/cmd/mesh-controller/group_wait.go @@ -8,6 +8,8 @@ import ( "strings" "time" + "github.com/nats-io/nats.go" + "github.com/novox/mesh-controller/internal/catalogue" "github.com/novox/mesh-controller/internal/inventory" "github.com/novox/mesh-controller/internal/link" @@ -60,13 +62,16 @@ var groupsAsked = func(ctx context.Context, held bool) ([]groupsLine, error) { if !held { return nil, fmt.Errorf("no holder of %s is on record to say it", catalogue.DeliverySeat) } - serving := servingBus.Load() - if serving == nil { - return nil, errors.New("this controller is not on the bus") - } - asking, cancel := context.WithTimeout(ctx, groupAskWithin) - defer cancel() - raw, err := askDeliveryOwner(asking, serving.Conn(), "groups", map[string]any{}) + // On the bus as this process is: the serving controller's own connection, lent, or — in a verb that runs as a command + // of its own, such as a recheck's `delivery check` — one dialled for the moment (onTheBus). + var raw json.RawMessage + err := onTheBus(func(conn *nats.Conn) error { + asking, cancel := context.WithTimeout(ctx, groupAskWithin) + defer cancel() + var err error + raw, err = askDeliveryOwner(asking, conn, "groups", map[string]any{}) + return err + }) if err != nil { if errors.Is(err, link.ErrNothingServes) { return nil, fmt.Errorf("nothing serves %s.groups", catalogue.DeliverySeat) diff --git a/cmd/mesh-controller/replay867_test.go b/cmd/mesh-controller/replay867_test.go index 9db90bd9..ac6b2add 100644 --- a/cmd/mesh-controller/replay867_test.go +++ b/cmd/mesh-controller/replay867_test.go @@ -67,6 +67,7 @@ type theIssue867 struct { js interface{ Conn() *nats.Conn } judgeCache string registry string + groups string // what mesh-delivery's groups answers } func r867Git(t *testing.T, dir string, args ...string) string { @@ -172,13 +173,14 @@ func theGroupOfIssue867(t *testing.T) *theIssue867 { if verb != "groups" { t.Fatalf("asked the owner %s", verb) } - return json.RawMessage(`[{"id":"feat/867","members":["` + root + `/mesh-host@` + r.hostHead[:12] + ` (checked)","` + - root + `/mesh-controller@` + r.controllerHead[:12] + ` (checked)"],"member_details":[` + - `{"id":"novox/mesh-host@` + r.hostHead[:12] + `","repository":"novox/mesh-host","state":"checked","number":114,"head":"` + - r.hostHead + `","base":"main","open":true},` + - `{"id":"novox/mesh-controller@` + r.controllerHead[:12] + `","repository":"novox/mesh-controller","state":"checked","number":346,"head":"` + - r.controllerHead + `","base":"main","open":true}]}]`), nil + return json.RawMessage(r.groups), nil } + r.groups = (`[{"id":"feat/867","members":["` + root + `/mesh-host@` + r.hostHead[:12] + ` (checked)","` + + root + `/mesh-controller@` + r.controllerHead[:12] + ` (checked)"],"member_details":[` + + `{"id":"novox/mesh-host@` + r.hostHead[:12] + `","repository":"novox/mesh-host","state":"checked","number":114,"head":"` + + r.hostHead + `","base":"main","open":true},` + + `{"id":"novox/mesh-controller@` + r.controllerHead[:12] + `","repository":"novox/mesh-controller","state":"checked","number":346,"head":"` + + r.controllerHead + `","base":"main","open":true}]}]`) r.registry = r867Registry(t) r867Runtime(t) return r @@ -301,3 +303,44 @@ exit 1 t.Setenv("PATH", dir+string(os.PathListSeparator)+os.Getenv("PATH")) t.Setenv("GOTOOLCHAIN", "local") } + +// A recheck runs as a command of its own (`delivery check` with one member), where the controller is not the serving +// one and holds no connection: it dials the bus for the moment and asks mesh-delivery's `groups` as the daemon does. +// This drives the verb on a test bus with a fake mesh-delivery answering `groups`, with no stub of the seam between. +func TestTheRecheckVerbAsksMeshDeliveryOnABusOfItsOwn(t *testing.T) { + realAsk := askDeliveryOwner + r := theGroupOfIssue867(t) + askDeliveryOwner = realAsk + js, _ := aBuildQueue(t) + if servingBus.Load() != nil { + t.Fatal("this test is of a process that is not the serving controller") + } + asked := 0 + wrapped, _ := json.Marshal(map[string]any{"content": []map[string]any{{"type": "text", "text": r.groups}}}) + sub, err := js.Conn().Subscribe(link.SeatToolSubject(catalogue.DeliverySeat, "groups"), func(m *nats.Msg) { + asked++ + body, _ := json.Marshal(link.Answer{Result: wrapped}) + _ = m.Respond(body) + }) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = sub.Unsubscribe() }) + member := `[{"id":"novox/mesh-host@` + r.hostHead[:12] + `","repository":"novox/mesh-host","base":"main","head":"` + + r.hostHead + `","number":114,"paths":["validate/more.go"],"module_dirs_said":true}]` + if err := deliveryCommand(t.Context(), []string{"check", "--members", member}); err != nil { + t.Fatal(err) + } + q, err := link.ReadQueue(t.Context(), js, link.TheBuildMachine) + if err != nil || len(q.Asks) == 0 { + t.Fatalf("nothing was asked of the build seat: %v", err) + } + c := q.Asks[len(q.Asks)-1].Request.Check + if c.SiblingsUnknown != "" || len(c.Siblings) != 1 || c.Siblings[0].Repository != "novox/mesh-controller" || + c.Siblings[0].Number != 346 || c.Siblings[0].Head != r.controllerHead { + t.Fatalf("the recheck learned siblings %+v, unknown %q", c.Siblings, c.SiblingsUnknown) + } + if asked != 1 { + t.Fatalf("mesh-delivery was asked %d times", asked) + } +} diff --git a/testdata/store-tests b/testdata/store-tests index 055495ac..ebafe258 100644 --- a/testdata/store-tests +++ b/testdata/store-tests @@ -81,3 +81,4 @@ ./cmd/mesh-controller TestARecordedMoveThatCannotBeJudgedWaits ./cmd/mesh-controller TestReplay867 ./cmd/mesh-controller TestReplay867Recheck +./cmd/mesh-controller TestTheRecheckVerbAsksMeshDeliveryOnABusOfItsOwn