diff --git a/modules/mesh-delivery-builder/builds/builds.go b/modules/mesh-delivery-builder/builds/builds.go index 8f175ed7..8981c7dc 100644 --- a/modules/mesh-delivery-builder/builds/builds.go +++ b/modules/mesh-delivery-builder/builds/builds.go @@ -48,12 +48,17 @@ func checkAskLanguage(language string) error { const ( // BuilderModule is the module of the builder part. BuilderModule = "mesh-delivery-builder" - // BuilderBuildsBucket is the builder's bucket of builds: `_`. - BuilderBuildsBucket = BuilderModule + "_builds" // BuilderBuildsHistory is the revisions the bucket keeps per key. BuilderBuildsHistory = 5 ) +// BuildsBucket is the builder's bucket of builds: `_builds`, of the module the builder runs as (its credential's), never +// a constant of its name (design 47 G A-296). +func BuildsBucket(module string) string { return StateBucket(module, "builds") } + +// StateBucket is the bus bucket of a module's state: `_`. +func StateBucket(module, state string) string { return module + "_" + state } + // The states of a build. const ( BuildQueued = "queued" diff --git a/modules/mesh-delivery-builder/builds/builds_test.go b/modules/mesh-delivery-builder/builds/builds_test.go index dbc554fa..55a18a37 100644 --- a/modules/mesh-delivery-builder/builds/builds_test.go +++ b/modules/mesh-delivery-builder/builds/builds_test.go @@ -203,8 +203,8 @@ func TestBuilderBuildVersion(t *testing.T) { // 1358/AC6: the builder's bucket and module do not collide with the controller's build layout (buildrecord.go), which // this change leaves as it was. func TestBuilderLayoutDoesNotCollideWithTheControllers(t *testing.T) { - if BuilderBuildsBucket != "mesh-delivery-builder_builds" || BuilderBuildsHistory != 5 || BuilderModule != "mesh-delivery-builder" { - t.Errorf("bucket %s history %d module %s", BuilderBuildsBucket, BuilderBuildsHistory, BuilderModule) + if BuildsBucket(BuilderModule) != "mesh-delivery-builder_builds" || BuilderBuildsHistory != 5 || BuilderModule != "mesh-delivery-builder" { + t.Errorf("bucket %s history %d module %s", BuildsBucket(BuilderModule), BuilderBuildsHistory, BuilderModule) } if buildrecord.BuildKey("m", "7") != "m.build.7" || buildrecord.NewestKey("m") != "m.newest" { t.Error("the controller's layout changed") diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go index 382bc39e..b05427b8 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder-tools/main.go @@ -125,7 +125,7 @@ func Tools(r build.StuckReader, askAgain func(key string, value []byte) error, q return nil, err } if err := askAgain(key, value); err != nil { - return nil, fmt.Errorf("the ask could not be written to %s: %w", build.ReAsksBucket, err) + return nil, fmt.Errorf("the ask could not be written to %s: %w", build.ReAsksState, err) } return map[string]any{"key": key, "asked": true, "next": "the builder answers in " + build.ReAsksState + "." + key + "; " + build.StuckTool + " shows the answer and the new ask"}, nil @@ -241,7 +241,7 @@ func Tools(r build.StuckReader, askAgain func(key string, value []byte) error, q // askQueue writes the queues value at key and waits, on a watch of the key, at most bound for the builder's answer. func askQueue(s stdio.KeptState, bound time.Duration) queueAsker { - return askKept(s, build.QueuesState, build.QueuesBucket, "the read", bound, func(v []byte) bool { + return askKept(s, build.QueuesState, builds.StateBucket(os.Getenv(stdio.ServedAs), build.QueuesState), "the read", bound, func(v []byte) bool { a, err := build.DecodeQueueAsk(v) return err == nil && !a.Answered.IsZero() }) @@ -353,7 +353,7 @@ func main() { _, err := reasks.Put(key, json.RawMessage(value)) return err } - buildAgain := askKept(reasks, build.ReAsksState, build.ReAsksBucket, "the request", 25*time.Second, func(v []byte) bool { + buildAgain := askKept(reasks, build.ReAsksState, builds.StateBucket(os.Getenv(stdio.ServedAs), build.ReAsksState), "the request", 25*time.Second, func(v []byte) bool { a, err := build.DecodeReAsk(v) return err == nil && !a.Answered.IsZero() }) @@ -398,7 +398,7 @@ func main() { return e.Value, true, nil }} // The catalog half's view of the packages the bundle follows itself (design 47 G §572, A-70), as other bundles follow views. - pk := &views.Reader{Module: builds.BuilderModule, Logf: func(f string, a ...any) { fmt.Fprintf(os.Stderr, "[mesh-delivery-builder-tools] "+f+"\n", a...) }, + pk := &views.Reader{Module: os.Getenv(stdio.ServedAs), Logf: func(f string, a ...any) { fmt.Fprintf(os.Stderr, "[mesh-delivery-builder-tools] "+f+"\n", a...) }, Acts: meshhandactsclient.Recorder{Ask: stdio.Ask}} branches, err := meshcatalogclient.FollowBranches(pk, stdio.Ask) if err != nil { @@ -457,7 +457,7 @@ func main() { tools = append(tools, enginereads.Tool(EngineReadsTool, "the builder", enginereads.KeptState(stdio.State("engine-reads")), true, time.Now)) // builder_first_views and builder_first_view_again: where the builder's first views of the indexer's and the assigner's // states stand, and asking one again by hand (ADR 0615, DLV-M1). - tools = append(tools, views.StatusTools(builds.BuilderModule, "builder_first_views", "builder_first_view_again", stdio.State(views.StatusState), meshhandactsclient.Recorder{Ask: stdio.Ask}, time.Now)...) + tools = append(tools, views.StatusTools(os.Getenv(stdio.ServedAs), "builder_first_views", "builder_first_view_again", stdio.State(views.StatusState), meshhandactsclient.Recorder{Ask: stdio.Ask}, time.Now)...) tools = append(tools, gate.Tools()...) if err := stdio.Serve("", tools); err != nil { fmt.Fprintf(os.Stderr, "[mesh-delivery-builder-tools] %v\n", err) diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/findings.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/findings.go index d184ad30..b50b6af3 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/findings.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/findings.go @@ -17,10 +17,6 @@ import ( "mesh-delivery-builder/internal/versions" ) -// findingsBucket is the builder's findings (novox/hq ADR 0564 §2): what it sees wrong now, written at its raise and -// deleted at its clear, which the condition keeper raises and clears. -var findingsBucket = builds.BuilderModule + "_" + mcseat.StateFindings - // heldWriter is the builder's finding writer: its findings are raised as they happen, so the writer holds them (design 47 G // A-29); its `findings-asked` subject is the seat's, from the generated contract (A-17). type heldWriter = views.HeldWriter[mcseat.Finding, mcseat.FindingCleared, mcseat.FindingsStated, mcseat.FindingsAskedEvent] @@ -34,9 +30,11 @@ type findingWriter interface { // findings writes the builder's findings through its held finding writer (design 47 G §689, A-29): a finding written before the // writer starts is held and stated at its start. type findings struct { - w findingWriter - logf func(string, ...any) - now func() time.Time + // module is the module the builder runs as, its credential's: the observer of every finding. + module string + w findingWriter + logf func(string, ...any) + now func() time.Time } // finding is one of the builder's findings: its kind, what it is about, and its words. @@ -48,7 +46,7 @@ type finding struct { } // seatFinding is fd as the seat's generated finding at at, its id made safe as a key's part. -func (fd finding) seatFinding(at time.Time) mcseat.Finding { +func (fd finding) seatFinding(module string, at time.Time) mcseat.Finding { at = at.UTC() id := keyID(fd.id) sev := fd.severity @@ -63,7 +61,7 @@ func (fd finding) seatFinding(at time.Time) mcseat.Finding { source = "builder." + fd.kind } return mcseat.Finding{Scope: fd.scope, ID: id, Kind: fd.kind, Severity: sev, Summary: fd.summary, Headline: fd.headline, - Explanation: fd.explanation, Needs: fd.needs, Source: source, Observer: builds.BuilderModule, At: at, + Explanation: fd.explanation, Needs: fd.needs, Source: source, Observer: module, At: at, Evidence: []mcseat.Evidence{{At: at, Said: said}}, Subject: mcseat.Subject{Scope: fd.scope, ID: id, Machine: fd.machine}} } @@ -107,7 +105,7 @@ func (f *findings) buildEnded(ctx context.Context, e builds.BuildLogEntry) { // raise writes fd through the writer. func (f *findings) raise(ctx context.Context, fd finding) { - x := fd.seatFinding(f.now()) + x := fd.seatFinding(f.module, f.now()) if f.w == nil { f.logf("finding %s (not written, no finding writer): %s", views.FindingKey(x.Scope, x.ID, x.Kind), x.Summary) return @@ -130,7 +128,7 @@ func (f *findings) clear(ctx context.Context, kind, scope, id string) { // notHeard is the writer of the builder's finding of a family it does not hear (heard.Writer, ADR 0615 §5): written through the // finding writer, said in the log until it starts. func (f *findings) notHeard(ctx context.Context) heard.Writer { - return heard.Writer{Observer: builds.BuilderModule, Logf: f.logf, Now: f.now, + return heard.Writer{Observer: f.module, Logf: f.logf, Now: f.now, Put: func(_ string, value []byte) error { var x mcseat.Finding if err := json.Unmarshal(value, &x); err != nil { diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go index 1bb200f4..aaf40603 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/integration_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "fmt" + mcseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" "maps" "os" "path/filepath" @@ -292,7 +293,7 @@ func startBedWith(t *testing.T, closed bool) *bed { t.Fatal(err) } viewstest.Serve(t, ctx, js, ctl, testAssigner, "assignments", testAssigner+".assignments", readers...) - b.builds = mk(builds.BuilderBuildsBucket, builds.BuilderBuildsHistory) + b.builds = mk(builds.BuildsBucket(builds.BuilderModule), builds.BuilderBuildsHistory) b.instances = mk(instancesBucket, 1) // The state bounds, whose keys have each its own time to live: an ask's step bounds (design 47 G A-77, A-118) are kept in it. if _, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: versions.BoundsBucket, History: 1, LimitMarkerTTL: time.Second}); err != nil { @@ -1120,8 +1121,8 @@ func (b *bed) registry(t *testing.T, node string, seatVersions ...string) *regis } return kv } - r.versions, r.findings, r.reasks = mk(versions.Bucket), mk(findingsBucket), mk(build.ReAsksBucket) - mk(versions.FloorWaitsBucket) + r.versions, r.findings, r.reasks = mk(versions.Bucket), mk(builds.StateBucket(builds.BuilderModule, mcseat.StateFindings)), mk(builds.StateBucket(builds.BuilderModule, build.ReAsksState)) + mk(builds.StateBucket(builds.BuilderModule, versions.FloorWaitsState)) // EVENTS with two seats' outcomes, and the forge bridge's stream (a branch's end): each with the builder's durable consumer. for stream, subjects := range map[string][]string{ eventsStream: {"mesh.mod.*.event.>", "mesh.seat.*.event.>"}, diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go index 07e6ad1e..844d2028 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go @@ -75,7 +75,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro return err } defer conn.Close() - buildsKV, err := process.EssentialBucket(ctx, js, "builder", builds.BuilderBuildsBucket, "claim or write a build key") + buildsKV, err := process.EssentialBucket(ctx, js, "builder", builds.BuildsBucket(cred.Module), "claim or write a build key") if err != nil { return err } @@ -91,8 +91,8 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // The module has one durable consumer of EVENTS: one hub pulls it and hands each message to the part that hears it (the // views reader and the builder's own events), started once every part is registered. hub := process.NewEventHub(logger.Printf) - reader := &views.ProcessReader{Module: builds.BuilderModule, Call: calls.Call, Logf: logger.Printf, Hub: hub} - findingsKV := process.AwaitBucket(ctx, js, conn, findingsBucket, "the builder's findings, a first view unanswered past its bound among them, are said in its log only", logger.Printf) + reader := &views.ProcessReader{Module: cred.Module, Call: calls.Call, Logf: logger.Printf, Hub: hub} + findingsKV := process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, mcseat.StateFindings), "the builder's findings, a first view unanswered past its bound among them, are said in its log only", logger.Printf) // The builder's findings are raised as they happen, so its one finding writer holds them (design 47 G A-29, §689): it // is started once the state is bound, and what is written before is stated at its start. fw, err := views.NewHeldWriter(views.WriterConfig[mcseat.Finding, mcseat.FindingCleared, mcseat.FindingsStated, mcseat.FindingsAskedEvent]{ @@ -144,7 +144,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro dead := &buildrun.DeadLetters{} // The state may not be on the bus yet when a delivery started the builder (the grants part creates it, issue 1790): it // is bound when the bus says it was created, and the latest hearing is written then. - hearingKV := process.AwaitBucket(ctx, js, conn, builds.BuilderModule+"_"+buildrun.HearingState, "builder_stuck cannot say whether DEAD_LETTERS is heard", logger.Printf) + hearingKV := process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, buildrun.HearingState), "builder_stuck cannot say whether DEAD_LETTERS is heard", logger.Printf) hearing := buildrun.NewDeadLetterHearing(ctx, buildrun.JetStreamDeadLetters{JS: js}, buildstep.AskLanguages, dead, logger.Printf, buildrun.SayHearing(ctx, hearingKV, logger.Printf)) defer hearing.Stop() @@ -157,11 +157,11 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // The builder numbers each trunk build at its claim (novox/hq design 51 *The versions*): its state versions, bound once // the bus holds it; the floor's three sources asked as its own account. versionsKV := process.AwaitBucket(ctx, js, conn, versions.Bucket, "no trunk build is numbered: each is built unnumbered and published by its digest", logger.Printf) - found := &findings{w: fw, logf: logger.Printf, now: time.Now} + found := &findings{module: cred.Module, w: fw, logf: logger.Printf, now: time.Now} floorWaits := &versions.FloorWaits{Holder: versions.HolderOf(branches), Logf: logger.Printf, Said: found.floorSaid(context.WithoutCancel(ctx))} // The names waiting on their floor are kept in the state floor-waits (DLV-B4): a restarted builder takes them in, so // their silent sources' events still wake them; until the state is bound they are kept here only. - process.AwaitBucket(ctx, js, conn, versions.FloorWaitsBucket, "the names waiting on their floor are kept in memory only, and builder_floor_waits shows none", logger.Printf). + process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, versions.FloorWaitsState), "the names waiting on their floor are kept in memory only, and builder_floor_waits shows none", logger.Printf). Ready(func(kv jetstream.KeyValue) { floorWaits.Keep(kvKeeper{ctx: ctx, kv: kv}, heldFloorWaits(ctx, kv, logger.Printf)) }) @@ -183,8 +183,9 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro } } b = &build.Builder{ - Claimer: build.Claimer{Store: kvStore{buildsKV}, By: cred.Node + "." + cred.Module}, - Seats: seats, + OwnModule: cred.Module, + Claimer: build.Claimer{Store: kvStore{buildsKV}, By: cred.Node + "." + cred.Module}, + Seats: seats, Asks: buildrun.Asker{Name: meshbuilds.Seat, Seats: seats, Publisher: asks, Waiter: buildrun.LostAskWaiter{Inner: heard, Dead: dead, Hearing: hearing}, Bound: bound, Dropper: buildrun.SeatDrops{Caller: calls}, Bounds: &stepBounds{bounds: pubBoundsKV.KV, js: js, now: time.Now, logf: logger.Printf}, Expiry: stepExpiry}, Held: heldOnTheBus{js: js, seats: seats}, @@ -209,7 +210,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro if err != nil { return err } - waitsBucket := process.AwaitBucket(ctx, js, conn, build.WaitsBucket, "the toolchain waits are kept in memory only, and builder_waits shows none", logger.Printf) + waitsBucket := process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, build.WaitsState), "the toolchain waits are kept in memory only, and builder_waits shows none", logger.Printf) b.Waits = newWaitsKept(waitsBucket, func(ctx context.Context, event, id string, body any) error { return emitEvent(context.WithoutCancel(ctx), js, cred, event, id, body) }, waitBound, logger.Printf) @@ -318,11 +319,12 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // What each counted node's engine reads (ADR 0618 §2, ADR 0624 §1): asked through the node-engine seat's verb as the // builder's own account, for every node the assignments names, and kept in the state engine-reads once it is bound. reads := newEngineReads(calls.CallKeptOn, gate, logger.Printf) + reads.module = cred.Module reads.keeper.Once = calls.CallOn // its fault keeps the last statement at once while the kept call asks on (ADR 0668 §3) // The old reference form's window over them (DLV-B9), kept in the state old-form once it is bound; builder_old_form // reads it and drops a retired node by hand. reads.ctx = context.WithoutCancel(ctx) - reads.window = &oldForm{forms: forms.Current, findings: found, logf: logger.Printf, now: time.Now, log: func(e builds.BuildLogEntry) { b.Log(e) }, + reads.window = &oldForm{module: cred.Module, forms: forms.Current, findings: found, logf: logger.Printf, now: time.Now, log: func(e builds.BuildLogEntry) { b.Log(e) }, bounds: pubBoundsKV.KV, said: func(body versions.OldFormClosedBody) { if err := emitEvent(context.WithoutCancel(ctx), js, cred, versions.OldFormClosedEvent, "old-form-closed-"+body.At.Format(time.RFC3339Nano), body); err != nil { @@ -336,7 +338,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro } return answer, err } - process.AwaitBucket(ctx, js, conn, versions.OldFormBucket, "the old form's window is kept in memory only, and builder_old_form shows none", logger.Printf). + process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, versions.OldFormState), "the old form's window is kept in memory only, and builder_old_form shows none", logger.Printf). Ready(func(kv jetstream.KeyValue) { reads.window.bind(context.WithoutCancel(ctx), kv) reads.stepWindow() @@ -435,7 +437,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro (&floorWake{b: b, waits: floorWaits, logf: logger.Printf}).wake(ctx, versions.WakeRevision, "", "") } // All of the catalog half's wiring is set before the reader starts: its views are heard on the reader's goroutines from then. - reader.Start(ctx, js, cred, process.AwaitBucket(ctx, js, conn, firstViewsBucket, "builder_first_views reads nothing and builder_first_view_again is not heard", logger.Printf)) + reader.Start(ctx, js, cred, process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, views.StatusState), "builder_first_views reads nothing and builder_first_view_again is not heard", logger.Printf)) // Every part has registered: the hub pulls the module's durable. Where the consumer is not there yet the builder says so // and binds it at a later change (heard.Writer; ADR 0615 §5). _ = notHeard.Bind(eventsStream, sweep.EventArtifactsGone+", what wakes a floor, the registry seats' words, the views and manifest-reads-changed are not heard until the builder starts again", func() error { @@ -445,10 +447,10 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // A person asks a key's build again with builder_ask_again, which writes the reasks state (issue 1945): watched, as // every other input. The builder asks again by itself without it. // A state not on the bus yet at this start is watched once it appears (issue 1790). - process.AwaitBucket(ctx, js, conn, build.ReAsksBucket, "builder_ask_again is not heard; an ask that can no longer be answered is still asked again by itself", logger.Printf).Ready(func(kv jetstream.KeyValue) { + process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, build.ReAsksState), "builder_ask_again is not heard; an ask that can no longer be answered is still asked again by itself", logger.Printf).Ready(func(kv jetstream.KeyValue) { eachReAsk := func(e jetstream.KeyValueEntry) { reAsked(ctx, b, acts, kv, e, logger.Printf) } if rw, err := settle(ctx, kv, eachReAsk); err != nil { - process.NotWatched(logger.Printf, build.ReAsksBucket, err, "builder_ask_again is not heard until the builder starts again") + process.NotWatched(logger.Printf, builds.StateBucket(cred.Module, build.ReAsksState), err, "builder_ask_again is not heard until the builder starts again") } else { go func() { errs <- follow(ctx, rw, eachReAsk) }() } @@ -490,19 +492,19 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro }) // A person reads a build seat's stream with builder_seat_queue, which writes the queues state (issue 1945 note 62): the // builder alone may read the stream, so it answers there. - process.AwaitBucket(ctx, js, conn, build.QueuesBucket, "builder_seat_queue is not answered", logger.Printf).Ready(func(kv jetstream.KeyValue) { + process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, build.QueuesState), "builder_seat_queue is not answered", logger.Printf).Ready(func(kv jetstream.KeyValue) { eachRead := func(e jetstream.KeyValueEntry) { queueRead(ctx, heldOnTheBus{js: js, seats: seats}, kv, e, logger.Printf) } if qw, err := settle(ctx, kv, eachRead); err != nil { - process.NotWatched(logger.Printf, build.QueuesBucket, err, "builder_seat_queue is not answered until the builder starts again") + process.NotWatched(logger.Printf, builds.StateBucket(cred.Module, build.QueuesState), err, "builder_seat_queue is not answered until the builder starts again") } else { go func() { errs <- follow(ctx, qw, eachRead) }() } }) // The state engine-reads, new with ADR 0618 (issue 1790's kind): until it is on the bus each statement is kept in memory // only, and builder_engine_reads answers nothing. - process.AwaitBucket(ctx, js, conn, engineReadsBucket, "what each node's engine reads is kept in memory only", logger.Printf).Ready(func(kv jetstream.KeyValue) { + process.AwaitBucket(ctx, js, conn, builds.StateBucket(cred.Module, EngineReadsState), "what each node's engine reads is kept in memory only", logger.Printf).Ready(func(kv jetstream.KeyValue) { reads.bind(ctx, kv, errs, logger.Printf) }) logger.Printf("started on %s", cred.Node) @@ -517,10 +519,6 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro } } -// The builder's own state of its first views (views.StatusState); its findings (findingsBucket) are where the condition -// keeper raises a first view unanswered past its bound (ADR 0615 §6). -var firstViewsBucket = builds.BuilderModule + "_" + views.StatusState - // toolchainWaitOf reads the toolchain wait's setting, toolchain-wait-minutes, from the file the manifest declares with the // content ${config:toolchain-wait-minutes} (design 47 G §672, A-71), at the builder's start: no file, or an empty one, is // the default; a content that is no number of minutes is an error naming the file. diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/oldform.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/oldform.go index c77e8dc9..2eb53671 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/oldform.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/oldform.go @@ -25,6 +25,8 @@ import ( // build key written, never on a timer. A node holding it seven days is the finding old-form-held; its close is said once // as version.old-form-closed and in the builder's log. type oldForm struct { + // module is the module the builder runs as, its credential's: the module of its build log entries. + module string forms forms.ArtifactForms findings *findings // said emits version.old-form-closed. @@ -119,7 +121,7 @@ func (o *oldForm) step(ctx context.Context, named []string, counted map[string][ // In the build log too (design 51 *The node-engine's own build*), under the builder's own key, the window's key // standing for the fingerprint: the close is no one build's. if o.log != nil { - o.log(builds.BuildLogEntry{Event: builds.BuildSaidEvent, Module: builds.BuilderModule, FP: versions.OldFormKey, + o.log(builds.BuildLogEntry{Event: builds.BuildSaidEvent, Module: o.module, FP: versions.OldFormKey, At: body.At.UTC(), Line: line, Why: versions.SaidOldFormClosed}) } if o.said != nil { diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reads.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reads.go index cd9a1702..524547a7 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reads.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reads.go @@ -22,11 +22,9 @@ import ( // with no key reads as stating the baseline: its first forms. No node's record is read in its place. const EngineReadsState = "engine-reads" -// engineReadsBucket is that state's bucket. -const engineReadsBucket = builds.BuilderModule + "_" + EngineReadsState - // engineReads keeps the statements and the counted nodes for the builder's forms (build.Builder.Forms). type engineReads struct { + module string keeper *enginereads.Keeper gate *buildrun.PlacedNodes mu sync.Mutex @@ -101,7 +99,7 @@ func (r *engineReads) bind(ctx context.Context, kv jetstream.KeyValue, errs chan } w, err := settle(ctx, kv, each) if err != nil { - process.NotWatched(logf, engineReadsBucket, err, "builder_engine_reads is not answered until the builder starts again") + process.NotWatched(logf, builds.StateBucket(r.module, EngineReadsState), err, "builder_engine_reads is not answered until the builder starts again") return } go func() { errs <- follow(ctx, w, each) }() diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/refused_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/refused_test.go index 80fcec9f..42a8cafe 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/refused_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/refused_test.go @@ -140,7 +140,7 @@ func theCountedNodesEngineReads(t *testing.T) { asked = append(asked, key, body) return json.Marshal(meshwatchdogs.PresenceAnswer{Machine: "n2", Online: online}) }) - calls := r2.callsOf(&findings{w: st, logf: t.Logf, now: clock}, func() jetstream.KeyValue { return nil }, heard, t.Logf) + calls := r2.callsOf(&findings{module: builds.BuilderModule, w: st, logf: t.Logf, now: clock}, func() jetstream.KeyValue { return nil }, heard, t.Logf) calls.Arm = func(_ context.Context, node string, ends time.Time) error { armed[node] = ends; return nil } key := meshconditionsclient.Key(meshconditionsclient.ScopeCall, "manifest-reads.n2", meshconditionsclient.KindCallUnanswered) r2.placed() // n2 asked, unanswered at 1000 @@ -303,7 +303,7 @@ func (failingVersions) KeysOf(context.Context, string) ([]string, error) { func aFailedTrunkBuildIsAFinding(t *testing.T) { st := &memFindings{vals: map[string][]byte{}} - f := &findings{w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} + f := &findings{module: builds.BuilderModule, w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} ended := func(outcome, ref string) builds.BuildLogEntry { return builds.BuildLogEntry{Event: builds.BuildEndedEvent, Module: "m", FP: "f1", Commit: "c", Ref: ref, Outcome: outcome} } @@ -440,10 +440,10 @@ func aFailedTrunkBuildIsAFinding(t *testing.T) { var closings []versions.OldFormClosedBody var logged []builds.BuildLogEntry marks := &memBounds{keys: map[string]bool{}} - window := &oldForm{forms: fs, findings: f, logf: t.Logf, now: func() time.Time { return now }, bounds: func() jetstream.KeyValue { return marks }, + window := &oldForm{module: builds.BuilderModule, forms: fs, findings: f, logf: t.Logf, now: func() time.Time { return now }, bounds: func() jetstream.KeyValue { return marks }, said: func(b versions.OldFormClosedBody) { closings = append(closings, b) }, log: func(e builds.BuildLogEntry) { logged = append(logged, e) }} - reads := &engineReads{keeper: &enginereads.Keeper{}, window: window, counted: []string{"a", "b"}} + reads := &engineReads{module: builds.BuilderModule, keeper: &enginereads.Keeper{}, window: window, counted: []string{"a", "b"}} // Issue 1966 note 155, ADR 0668 §4: at the consumer's bind every counted node is called once again. var boundCalls []string reads.keeper.Sync = true @@ -575,3 +575,14 @@ func decodeFinding(v []byte) (mcseat.Finding, error) { var f mcseat.Finding return f, json.Unmarshal(v, &f) } + +// Design 47 G A-296: the builder's findings are observed by the module its credential names, never a constant of its name. +func TestTheBuildersFindingsAreObservedByItsCredentialsModule(t *testing.T) { + st := &memFindings{vals: map[string][]byte{}} + f := &findings{module: "acme-builder", w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} + f.buildEnded(context.Background(), builds.BuildLogEntry{Event: builds.BuildEndedEvent, Module: "m", FP: "f1", Commit: "c", Outcome: builds.BuildFailed}) + got, err := decodeFinding(st.vals[meshconditionsclient.Key(meshconditionsclient.ScopeModule, "m", BuildFailed)]) + if err != nil || got.Observer != "acme-builder" { + t.Fatalf("the finding = %+v, %v; want the observer acme-builder", got, err) + } +} diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reserve_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reserve_test.go index 72c84c5a..274b5c45 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reserve_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/reserve_test.go @@ -3,6 +3,7 @@ package main import ( "context" "encoding/json" + "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "strings" "testing" "time" @@ -76,7 +77,7 @@ func (b *boundsKV) Delete(_ context.Context, key string, _ ...jetstream.KVDelete func TestTheCatalogsWordsMoveTheReservations(t *testing.T) { ctx := context.Background() st := &memFindings{vals: map[string][]byte{}} - found := &findings{w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} + found := &findings{module: builds.BuilderModule, w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} bounds := &boundsKV{keys: map[string]bool{}} woke := 0 call := func(addr string, body any) (json.RawMessage, error) { @@ -155,7 +156,7 @@ func TestAReleasedVersionIsTaggedAtTheCommitItWasBuiltFrom(t *testing.T) { tags = append(tags, body.(git.TagInput)) return json.Marshal(git.TagAnswer{Performed: refuse == "", Error: refuse}) } - found := &findings{w: &memFindings{vals: map[string][]byte{}}, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} + found := &findings{module: builds.BuilderModule, w: &memFindings{vals: map[string][]byte{}}, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} rv := newReservations(&memReserve{vals: map[string][]byte{}, revs: map[string]uint64{}}, call, func() jetstream.KeyValue { return &boundsKV{keys: map[string]bool{}} }, found, nil, t.Logf) rv.filled.Store(true) goPkg := versions.Source{Repository: "o/r", Commit: "c0ffee", GoPackage: true} diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/stepsread_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/stepsread_test.go index d47b9c4d..9840ca65 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/stepsread_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/stepsread_test.go @@ -3,6 +3,7 @@ package main import ( "context" "errors" + "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "strings" "testing" "time" @@ -18,7 +19,7 @@ import ( // while the read is unanswered raises call-unanswered about the ask; the answer deletes the bound and clears the finding. func TestTheStepsReadIsCallUnansweredAfterItsBound(t *testing.T) { st := &memFindings{vals: map[string][]byte{}} - f := &findings{w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} + f := &findings{module: builds.BuilderModule, w: st, logf: t.Logf, now: func() time.Time { return time.Unix(0, 0) }} marks := &memBounds{keys: map[string]bool{}} s := &stepsRead{bounds: func() jetstream.KeyValue { return marks }, findings: f, bound: meshconditionsclient.CallUnansweredAfter, now: func() time.Time { return time.Unix(600, 0) }, logf: t.Logf} diff --git a/modules/mesh-delivery-builder/internal/build/queue.go b/modules/mesh-delivery-builder/internal/build/queue.go index ea5b9903..329ee568 100644 --- a/modules/mesh-delivery-builder/internal/build/queue.go +++ b/modules/mesh-delivery-builder/internal/build/queue.go @@ -6,7 +6,6 @@ import ( "strings" "time" - "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/buildstep" ) @@ -19,8 +18,7 @@ import ( const ( SeatQueueTool = "builder_seat_queue" // QueuesState is the builder's state of queue reads: the bucket mesh-delivery-builder_queues, keyed by the language. - QueuesState = "queues" - QueuesBucket = builds.BuilderModule + "_" + QueuesState + QueuesState = "queues" // DefaultQueueLimit and MaxQueueLimit bound the messages read of each kind. DefaultQueueLimit = 50 MaxQueueLimit = 500 diff --git a/modules/mesh-delivery-builder/internal/build/run.go b/modules/mesh-delivery-builder/internal/build/run.go index 7f743f31..5e0b5bea 100644 --- a/modules/mesh-delivery-builder/internal/build/run.go +++ b/modules/mesh-delivery-builder/internal/build/run.go @@ -40,7 +40,9 @@ type ToolchainEntries interface { // pulled by whichever build node has a free slot: ADR 0525), and writes the key done or failed. It holds no timer; a build starts from a modules value or a // change of the toolchains. type Builder struct { - Claimer Claimer + // OwnModule is the module the builder runs as, its credential's: the asker of every step ask. + OwnModule string + Claimer Claimer // StepEntry reads the entry of a fingerprint through the seat mesh-catalog's entry (design 47 G A-84, A-97). StepEntry func(ctx context.Context, fingerprint string) (meshcatalog.CatalogEntry, error) // Seats finds the build modules: the holders of the build seats on the seat list and the catalog half (design 47 G A-82). @@ -1065,7 +1067,7 @@ func (b *Builder) runLane(ctx context.Context, l *lane, repository string, m mes if needsFetch(l.tasks) { job.Fetch = &req } - ask := sdkstep.StepAsk{ID: sdkstep.NewID(), Kind: kind, Language: language, Asker: builds.BuilderModule, At: time.Now(), Version: l.version, Build: job} + ask := sdkstep.StepAsk{ID: sdkstep.NewID(), Kind: kind, Language: language, Asker: b.OwnModule, At: time.Now(), Version: l.version, Build: job} if language == sdkstep.AskGo && job.Fetch != nil && len(m.Packages) > 0 { // The versions of the mesh packages the fingerprint was computed with (novox/hq ADR 0573 §2): the build module writes // them into the workspace, whatever the repository's go.mod names. diff --git a/modules/mesh-delivery-builder/internal/build/run_test.go b/modules/mesh-delivery-builder/internal/build/run_test.go index 377f883e..1d0d2bef 100644 --- a/modules/mesh-delivery-builder/internal/build/run_test.go +++ b/modules/mesh-delivery-builder/internal/build/run_test.go @@ -185,7 +185,7 @@ func newRig(t *testing.T, artifacts ...catalogue.Artifact) *rig { r.tools.Set(n, tcOf("typescript", "tsc5")) } r.asks = &buildrun.FakeAsks{Answer: r.answer} - r.b = &Builder{ + r.b = &Builder{OwnModule: builds.BuilderModule, Seats: testSeats(), Claimer: Claimer{Store: r.st, By: "novox.builder"}, Asks: buildrun.Asker{Seats: testSeats(), Publisher: r.asks, Waiter: r.asks, Bound: 2 * time.Second}, Toolchains: r.tools, Manifests: r.mf, Logf: t.Logf, } @@ -594,7 +594,7 @@ func TestAKeyTheBuilderLeftBuildingIsBuiltAtStartAndDoneKeysAreNotBuiltTwice(t * // whose compare-and-set comes first, and the other's write is refused, never overwriting it. func TestTwoInstancesStartingTogetherEndWithOneDoneKey(t *testing.T) { // 1607/AC7, review round 4 r := newRig(t, goBundle) - other := &Builder{Claimer: Claimer{Store: r.st, By: "ace.builder"}, Asks: r.b.Asks, Toolchains: r.tools, Manifests: r.mf, Logf: t.Logf} + other := &Builder{OwnModule: builds.BuilderModule, Claimer: Claimer{Store: r.st, By: "ace.builder"}, Asks: r.b.Asks, Toolchains: r.tools, Manifests: r.mf, Logf: t.Logf} value := moduleValue(t, "modules/m") var wg sync.WaitGroup for _, b := range []*Builder{r.b, other} { diff --git a/modules/mesh-delivery-builder/internal/build/stuck.go b/modules/mesh-delivery-builder/internal/build/stuck.go index 677a09e2..9f156410 100644 --- a/modules/mesh-delivery-builder/internal/build/stuck.go +++ b/modules/mesh-delivery-builder/internal/build/stuck.go @@ -31,8 +31,7 @@ const ( // of Mode ModeAnnounce. AnnounceAgainTool = "builder_announce_again" // ReAsksState is the builder's state of asks to ask again: the bucket mesh-delivery-builder_reasks, keyed as the build key. - ReAsksState = "reasks" - ReAsksBucket = builds.BuilderModule + "_" + ReAsksState + ReAsksState = "reasks" ) // ReAsk is a value of the reasks state: why a person asked the key's build again, who and when, and, once the builder diff --git a/modules/mesh-delivery-builder/internal/build/waits.go b/modules/mesh-delivery-builder/internal/build/waits.go index d314976c..e51f0b14 100644 --- a/modules/mesh-delivery-builder/internal/build/waits.go +++ b/modules/mesh-delivery-builder/internal/build/waits.go @@ -21,8 +21,7 @@ const ( WaitsTool = "builder_waits" ReleaseTool = "builder_release" // WaitsState is the builder's old state section of the waits, one key .. - WaitsState = "waits" - WaitsBucket = builds.BuilderModule + "_" + WaitsState + WaitsState = "waits" // ModeRelease is the Mode of a reasks value of builder_release. ModeRelease = "release" // WaitRan ends a wait when a toolchain-agreed names the version; WaitReleased when builder_release ended it. diff --git a/modules/mesh-delivery-builder/internal/versions/floor.go b/modules/mesh-delivery-builder/internal/versions/floor.go index df838ce2..2ef45300 100644 --- a/modules/mesh-delivery-builder/internal/versions/floor.go +++ b/modules/mesh-delivery-builder/internal/versions/floor.go @@ -110,9 +110,8 @@ func (w FloorWait) Finding() string { // The builder's state floor-waits (DLV-B4): each name waiting on its floor, keyed by its escaped name, so a restarted // builder still knows which names its silent sources' events wake; builder_floor_waits reads it. const ( - FloorWaitsState = "floor-waits" - FloorWaitsBucket = "mesh-delivery-builder_floor-waits" - FloorWaitsTool = "builder_floor_waits" + FloorWaitsState = "floor-waits" + FloorWaitsTool = "builder_floor_waits" ) // FloorWaitKey is a wait's key in floor-waits. diff --git a/modules/mesh-delivery-builder/internal/versions/oldform.go b/modules/mesh-delivery-builder/internal/versions/oldform.go index 5262b492..f7730ac4 100644 --- a/modules/mesh-delivery-builder/internal/versions/oldform.go +++ b/modules/mesh-delivery-builder/internal/versions/oldform.go @@ -9,7 +9,6 @@ import ( "strings" "time" - "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds/forms" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/window" ) @@ -28,9 +27,6 @@ const ( OldFormKey = "window" ) -// OldFormBucket is that state's bucket. -const OldFormBucket = builds.BuilderModule + "_" + OldFormState - // OldFormHeld is the finding of a node holding the window open for FindingAfter, about that node, cleared when the // window closes or the node no longer holds it. const OldFormHeld = "old-form-held" diff --git a/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go b/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go index 20ee2d97..45e89227 100644 --- a/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go +++ b/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/integration_test.go @@ -607,7 +607,7 @@ func startBed(t *testing.T) *bed { check.CheckerOwedBucket: 5, check.PreviewsBucket: 5, check.CandidatesBucket: 10, check.ModulesBucket: 20, check.ManifestsBucket: 1, check.PresenceBucket: 20, check.HaveBucket: 20, check.TriesBucket: 1, - builds.BuilderBuildsBucket: 1, check.InputsBucket: 1} { + builds.BuildsBucket(builds.BuilderModule): 1, check.InputsBucket: 1} { kv, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: name, History: uint8(history)}) if err != nil { t.Fatal(err) @@ -850,7 +850,7 @@ func TestCheckerJudgesACandidateAndOwesItsStatus(t *testing.T) { // N6/AC5, 1300 } bkey, _ := builds.BuilderBuildKey("m", fp) building, _ := json.Marshal(builds.BuilderBuild{V: 1, State: builds.BuildBuilding}) - if _, err := b.buckets[builds.BuilderBuildsBucket].Put(b.ctx, bkey, building); err != nil { + if _, err := b.buckets[builds.BuildsBucket(builds.BuilderModule)].Put(b.ctx, bkey, building); err != nil { t.Fatal(err) } if v := b.verdict(t, key, func(meshdeliverychecker.VerdictsByGroupHeadsValue) bool { return true }); v.State != meshdeliverycheckerclient.VerdictRunning || len(asked()) != 0 { @@ -859,14 +859,14 @@ func TestCheckerJudgesACandidateAndOwesItsStatus(t *testing.T) { // N6/AC5, 1300 // m's build fails: the check fails naming it. Built again (builder_build_again writes the key done), the check asks // itself again for the same heads, with no recheck, and passes. failedBuild, _ := json.Marshal(builds.BuilderBuild{V: 1, State: builds.BuildFailed, Error: "go build: undefined: x"}) - if _, err := b.buckets[builds.BuilderBuildsBucket].Put(b.ctx, bkey, failedBuild); err != nil { + if _, err := b.buckets[builds.BuildsBucket(builds.BuilderModule)].Put(b.ctx, bkey, failedBuild); err != nil { t.Fatal(err) } if v := b.verdict(t, key, ended); v.State != meshdeliverycheckerclient.VerdictFail || v.Failed.Test != check.BuildFailedTest+"m" { t.Fatalf("verdict %+v, want it failed on m's build", v) } built, _ := json.Marshal(builds.BuilderBuild{V: 1, State: builds.BuildDone, Manifest: digest}) - if _, err := b.buckets[builds.BuilderBuildsBucket].Put(b.ctx, bkey, built); err != nil { + if _, err := b.buckets[builds.BuildsBucket(builds.BuilderModule)].Put(b.ctx, bkey, built); err != nil { t.Fatal(err) } b.said(t, "the builds of m it failed on are done again, so it is checked again") diff --git a/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/main.go b/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/main.go index ffb2a79d..e213a4b6 100644 --- a/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/main.go +++ b/modules/mesh-delivery-checker/cmd/mesh-delivery-checker/main.go @@ -276,7 +276,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // says nothing of the builds, until the checker starts again. var buildStates check.BuildStates var ends check.BuildEnds - if kv := process.OptionalBucket(ctx, js, builds.BuilderBuildsBucket, "the line says nothing of the builds, and a check composes without waiting on them, until the checker starts again", logger.Printf); kv != nil { + if kv := process.OptionalBucket(ctx, js, builds.BuildsBucket(builds.BuilderModule), "the line says nothing of the builds, and a check composes without waiting on them, until the checker starts again", logger.Printf); kv != nil { buildStates, ends = buildReader{kvStore{kv}}, buildEnds{kv} } if ends != nil { diff --git a/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go b/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go index 0f877a1e..301cc780 100644 --- a/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go +++ b/modules/mesh-delivery-view/cmd/mesh-delivery-view/main.go @@ -177,7 +177,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // The watchman's stuck keys name the wants' real bucket at their holder (A-303 (corrected)). model.SetWantsHolder(func() string { return reader.HolderBucket(meshwants.Seat, meshwants.StateWants) }) open := buckets{js: js, reader: reader} - for _, bucket := range []string{view.HaveBucket, view.AssignmentsBucket, view.PresenceBucket, view.StuckBucket, view.CandidatesBucket, view.AnswersBucket, builds.BuilderBuildsBucket, view.WantsBucket, view.AsksBucket, own.Answers, view.TakenBucket, own.Reach} { + for _, bucket := range []string{view.HaveBucket, view.AssignmentsBucket, view.PresenceBucket, view.StuckBucket, view.CandidatesBucket, view.AnswersBucket, builds.BuildsBucket(builds.BuilderModule), view.WantsBucket, view.AsksBucket, own.Answers, view.TakenBucket, own.Reach} { go follow(ctx, open, bucket, false, model, logger) } // The view's own state reach, as it stood at the start, is what the derivation lays its history over (design 47 G A-225); diff --git a/modules/mesh-delivery-view/internal/view/fingerprints_newform_test.go b/modules/mesh-delivery-view/internal/view/fingerprints_newform_test.go index b68f8be2..6def7e38 100644 --- a/modules/mesh-delivery-view/internal/view/fingerprints_newform_test.go +++ b/modules/mesh-delivery-view/internal/view/fingerprints_newform_test.go @@ -24,7 +24,7 @@ func builderKey(t *testing.T, module, fp2 string, b builds.BuilderBuild) Entry { if err != nil { t.Fatal(err) } - return Entry{Bucket: builds.BuilderBuildsBucket, Key: key, Value: data, At: t0} + return Entry{Bucket: builds.BuildsBucket(builds.BuilderModule), Key: key, Value: data, At: t0} } func TestAFingerprintOfTheNewFormIsShownAgainstItsBuilderKey(t *testing.T) { // I5 diff --git a/modules/mesh-delivery-view/internal/view/view.go b/modules/mesh-delivery-view/internal/view/view.go index 9e1cade5..f48b30dd 100644 --- a/modules/mesh-delivery-view/internal/view/view.go +++ b/modules/mesh-delivery-view/internal/view/view.go @@ -689,7 +689,7 @@ func (m *Model) apply(e Entry) { delete(m.answerOf, e.Key) } m.answers[e.Key] = id - case builds.BuilderBuildsBucket: + case builds.BuildsBucket(builds.BuilderModule): if e.Deleted { delete(m.keys, e.Key) return diff --git a/modules/mesh-grants/internal/buscompose/state.go b/modules/mesh-grants/internal/buscompose/state.go index b489d2a8..eff9a39c 100644 --- a/modules/mesh-grants/internal/buscompose/state.go +++ b/modules/mesh-grants/internal/buscompose/state.go @@ -358,7 +358,7 @@ const ResolvedBucket = "mesh-config_resolved" func NodeComposeReads(node string) []string { var out []string for _, bucket := range []string{AssignmentsBucket, AssignmentsCandidatesBucket, ModulesBucket, - ManifestsBucket, builds.BuilderBuildsBucket} { + ManifestsBucket, builds.BuildsBucket(builds.BuilderModule)} { out = append(out, readGrants(bucket, "")...) } return append(out, readGrants(ResolvedBucket, node+".>")...)