The steps of the build seats are watched and read by their holders: no caller of BuildModuleOf is left but the view's
The watchman asks the seat that places modules who holds each build seat (seatlist.HolderOf) and watches that holder's steps; its manifest reads the seats' steps and invokes the seat's assignments. The builder's stuck reader looks a step up by its seat, the tests find the holders on their test seat list, the watchman's integration bed answers who holds a seat. Its manifest tests take the manifest's requires. Builds: design 47 G A-82, A-126 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -171,7 +171,7 @@ func (r *BuildReader) stepNode(v builds.BuilderBuild) string {
|
||||
}
|
||||
slices.Sort(languages)
|
||||
for _, l := range languages {
|
||||
bm, _ := buildstep.BuildModuleOf(l)
|
||||
bm, _ := buildstep.BuildSeat(l) // the steps are by build seat (StuckReader.Steps)
|
||||
st, ok := r.Steps.Steps[bm]
|
||||
k, found := r.index[bm][v.Asks[l]]
|
||||
if !ok || !found {
|
||||
|
||||
@@ -154,7 +154,8 @@ func (r *rig) answer(a buildstep.StepAsk) buildstep.Step {
|
||||
if node == "" {
|
||||
node = "ace"
|
||||
}
|
||||
module, _ := buildstep.BuildModuleOf(a.Language)
|
||||
bm, _ := testSeats().OfAskLanguage(a.Language)
|
||||
module := bm.Module
|
||||
runner := buildrun.Runner{Caller: r.bm, Steps: r.bm.steps, Bound: time.Second}
|
||||
tool := func(name string) stepFunc {
|
||||
return func(ctx context.Context, args map[string]any) (any, error) {
|
||||
|
||||
@@ -212,7 +212,8 @@ var toolPrefix = map[string]string{goBuildModule: "build_go_", nodeBuildModule:
|
||||
// answer runs a check ask as the build module that pulls it does (gobuild.RunAsk), with the fake tools on shanks and the
|
||||
// bench's kept verdicts, and answers the step it writes.
|
||||
func (b *bench) answer(a buildstep.StepAsk) buildstep.Step {
|
||||
module, _ := buildstep.BuildModuleOf(a.Language)
|
||||
bm, _ := testSeats().OfAskLanguage(a.Language)
|
||||
module := bm.Module
|
||||
const node = "shanks"
|
||||
tool := func(name string) gobuild.StepFunc {
|
||||
return func(ctx context.Context, args map[string]any) (any, error) {
|
||||
|
||||
@@ -69,6 +69,14 @@ func serveOwners(t *testing.T, ctx context.Context, js jetstream.JetStream, nc *
|
||||
t.Helper()
|
||||
viewstest.Serve(t, ctx, js, nc, watch.AssignerModule, wantsState, watch.AssignerModule+".assigner_read_wants", "n1_"+watch.WatchmanModule)
|
||||
viewstest.Serve(t, ctx, js, nc, watch.IndexerModule, modulesState, watch.IndexerModule+".indexer_read_modules", "n1_"+watch.WatchmanModule)
|
||||
// The seat that places modules says who holds each build seat (design 47 G A-126): the module whose steps the watchman watches.
|
||||
held, _ := json.Marshal(map[string]any{"result": map[string]any{"seats": []map[string]any{
|
||||
{"seat": "node-build-go", "holders": []map[string]string{{"module": "mesh-build-go"}}}}}, "node": "ctl"})
|
||||
for _, subject := range []string{"mesh.seat.mesh-module-assigner.call.assignments", "mesh.seat.mesh-module-assigner.call.assignments.>"} {
|
||||
if _, err := nc.Subscribe(subject, func(m *nats.Msg) { _ = m.Respond(held) }); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// findingsStream is the watchman's own stream of its findings' events (design 47 G §383), which its finding writer says into.
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
"git.novox.be/novox/mesh-sdk/go/seatlist"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
@@ -345,7 +346,16 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
// keeps no steps bucket (yet) is said and left; the asks of its stream are mirrored all the same.
|
||||
taken := map[string]jetstream.KeyWatcher{}
|
||||
for _, lang := range buildstep.AskLanguages {
|
||||
module, _ := buildstep.BuildModuleOf(lang)
|
||||
seat, err := buildstep.BuildSeat(lang)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// The build module is the holder of the build seat (design 47 G A-82, A-126): asked of the seat that places modules.
|
||||
module, err := seatlist.HolderOf(calls.Call, seat)
|
||||
if err != nil {
|
||||
logger.Printf("the steps of %s cannot be read (%v): its asks are mirrored and never seen taken", seat, err)
|
||||
continue
|
||||
}
|
||||
kv, err := js.KeyValue(ctx, watch.StepsBucket(module))
|
||||
if err != nil {
|
||||
logger.Printf("the steps of %s cannot be read (%v): its asks are mirrored and never seen taken", module, err)
|
||||
|
||||
@@ -39,5 +39,5 @@ const (
|
||||
FindingNodeAccountFallback = "node-account-fallback"
|
||||
)
|
||||
|
||||
// StepsBucket is a build module's state steps (reads: mesh-build-go.steps, mesh-build-image.steps, mesh-build-node.steps).
|
||||
// StepsBucket is a build module's state steps (reads: the build seats' steps, `seat:node-build-<language>.steps`, held by the module that holds the seat).
|
||||
func StepsBucket(module string) string { return module + "_steps" }
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"mesh-delivery-watchman/internal/watch"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/seatlist"
|
||||
)
|
||||
|
||||
// The controller's manifest reader is mesh-controller internal/catalogue (ParseManifest), an internal package of another
|
||||
@@ -56,6 +58,7 @@ type manifest struct {
|
||||
Reads []string `json:"reads"`
|
||||
Consumes []string `json:"consumes"`
|
||||
Invokes []string `json:"invokes"`
|
||||
Requires []any `json:"requires"`
|
||||
State []state `json:"state"`
|
||||
Streams []struct {
|
||||
Name string `json:"name"`
|
||||
@@ -101,8 +104,9 @@ func TestManifestStateAndReads(t *testing.T) { // 1135/AC6
|
||||
}
|
||||
reads := slices.Clone(m.Reads)
|
||||
slices.Sort(reads)
|
||||
if !reflect.DeepEqual(reads, []string{"mesh-build-go.steps", "mesh-build-image.steps", "mesh-build-node.steps",
|
||||
"mesh-delivery-builder.builds", "mesh-host.health", "mesh-provisioner.provisions", "node-engine.have"}) {
|
||||
// The build modules are no names (design 47 G A-82): the steps are the states of the holders of the build seats.
|
||||
if !reflect.DeepEqual(reads, []string{"mesh-delivery-builder.builds", "mesh-host.health", "mesh-provisioner.provisions", "node-engine.have",
|
||||
"seat:node-build-go.steps", "seat:node-build-image.steps", "seat:node-build-node.steps"}) {
|
||||
t.Errorf("reads = %v", reads)
|
||||
}
|
||||
// Design 47 G §368: the version is MAJOR.MINOR and nothing else.
|
||||
@@ -123,7 +127,7 @@ func TestManifestStateAndReads(t *testing.T) { // 1135/AC6
|
||||
}
|
||||
// The join: its first view asked again by hand is a hand act, recorded through the seat (views.StatusTools). The waits the
|
||||
// indexer holds at the watchman's start are asked of its tool (ADR 0633 §5), a verb edge as the view's.
|
||||
if want := []string{"mesh-delivery-assigner.assigner_read_wants", "mesh-delivery-indexer.indexer_pending", "mesh-delivery-indexer.indexer_read_modules", "seat:mesh-hand-acts.hand-act"}; !reflect.DeepEqual(m.Invokes, want) {
|
||||
if want := []string{"mesh-delivery-assigner.assigner_read_wants", "mesh-delivery-indexer.indexer_pending", "mesh-delivery-indexer.indexer_read_modules", "seat:mesh-hand-acts.hand-act", "seat:mesh-module-assigner.assignments"}; !reflect.DeepEqual(m.Invokes, want) {
|
||||
t.Errorf("invokes = %v, want %v", m.Invokes, want)
|
||||
}
|
||||
// DLV-M5 its first views, 1585/T20 the indexer's take-in events, and DLV-W1 (ADR 0595 §4): the accepted verdicts and the bus module's created and refused, durably.
|
||||
@@ -165,14 +169,16 @@ func TestManifestStateAndReads(t *testing.T) { // 1135/AC6
|
||||
return e
|
||||
}
|
||||
for name, row := range map[string]struct{ got, want string }{
|
||||
"module": {watch.WatchmanModule, m.Module},
|
||||
"presence": {watch.PresenceBucket, m.Module + "_" + m.State[0].Name},
|
||||
"pulse": {watch.PulseBucket, m.Module + "_" + m.State[1].Name},
|
||||
"stuck": {watch.StuckBucket, m.Module + "_" + m.State[2].Name},
|
||||
"have": {watch.HaveBucket, bucket(m.Reads, "node-engine.have")},
|
||||
"health": {watch.NodeHealthBucket, bucket(m.Reads, "mesh-host.health")},
|
||||
"builds": {watch.BuilderBuildsBucket, bucket(m.Reads, "mesh-delivery-builder.builds")},
|
||||
"steps": {watch.StepsBucket("mesh-build-go"), bucket(m.Reads, "mesh-build-go.steps")},
|
||||
"module": {watch.WatchmanModule, m.Module},
|
||||
"presence": {watch.PresenceBucket, m.Module + "_" + m.State[0].Name},
|
||||
"pulse": {watch.PulseBucket, m.Module + "_" + m.State[1].Name},
|
||||
"stuck": {watch.StuckBucket, m.Module + "_" + m.State[2].Name},
|
||||
"have": {watch.HaveBucket, bucket(m.Reads, "node-engine.have")},
|
||||
"health": {watch.NodeHealthBucket, bucket(m.Reads, "mesh-host.health")},
|
||||
"builds": {watch.BuilderBuildsBucket, bucket(m.Reads, "mesh-delivery-builder.builds")},
|
||||
// The build modules are no names (design 47 G A-82): the steps are read as the states of the holders of the build seats.
|
||||
"steps": {"seat:node-build-go.steps", entry(m.Reads, "seat:node-build-go.steps")},
|
||||
"holders": {"seat:" + seatlist.HolderSeat + "." + seatlist.HolderVerb, entry(m.Invokes, "seat:"+seatlist.HolderSeat+"."+seatlist.HolderVerb)},
|
||||
"wants": {watch.AssignerWantsBucket, bucket(m.Consumes, "mesh-delivery-assigner.views.wants")},
|
||||
"provisions": {watch.ProvisionsBucket, bucket(m.Reads, "mesh-provisioner.provisions")},
|
||||
"modules": {watch.ModulesBucket, bucket(m.Consumes, "mesh-delivery-indexer.views.modules")},
|
||||
|
||||
@@ -16,19 +16,20 @@
|
||||
}
|
||||
],
|
||||
"reads": [
|
||||
"mesh-build-go.steps",
|
||||
"mesh-build-image.steps",
|
||||
"mesh-build-node.steps",
|
||||
"mesh-delivery-builder.builds",
|
||||
"mesh-host.health",
|
||||
"mesh-provisioner.provisions",
|
||||
"node-engine.have"
|
||||
"node-engine.have",
|
||||
"seat:node-build-go.steps",
|
||||
"seat:node-build-image.steps",
|
||||
"seat:node-build-node.steps"
|
||||
],
|
||||
"invokes": [
|
||||
"mesh-delivery-assigner.assigner_read_wants",
|
||||
"mesh-delivery-indexer.indexer_pending",
|
||||
"mesh-delivery-indexer.indexer_read_modules",
|
||||
"seat:mesh-hand-acts.hand-act"
|
||||
"seat:mesh-hand-acts.hand-act",
|
||||
"seat:mesh-module-assigner.assignments"
|
||||
],
|
||||
"consumes": [
|
||||
"mesh-delivery-assigner.views.wants",
|
||||
|
||||
Reference in New Issue
Block a user