Merge branch 'b7f/registry' into b7/registry
This commit is contained in:
@@ -10,11 +10,13 @@ import (
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
"io"
|
||||
"maps"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
@@ -39,7 +41,6 @@ import (
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"git.novox.be/novox/mesh-sdk/go/buscompose"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
||||
@@ -121,7 +122,7 @@ func startBed(t *testing.T, leaveOut string) *bed {
|
||||
// event names the engine's machine last, so the filter is the event with every machine (mesh-grants buscompose
|
||||
// machineEvent; the grants part's own test holds the derivation).
|
||||
if _, err := js.CreateOrUpdateConsumer(ctx, "EVENTS", jetstream.ConsumerConfig{Durable: "n1_mesh-delivery-assigner",
|
||||
FilterSubjects: []string{enginereads.SubjectPrefix + "*", "mesh.mod." + delivery.IndexerModule + ".event.views.>"}, AckPolicy: jetstream.AckExplicitPolicy}); err != nil {
|
||||
FilterSubjects: []string{enginereads.SubjectPrefix + "*", "mesh.mod." + meshcatalogclient.Module + ".event.views.>"}, AckPolicy: jetstream.AckExplicitPolicy}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The operator-channel seat's stream of conditions, which the assigner says its conditions on.
|
||||
@@ -137,7 +138,7 @@ func startBed(t *testing.T, leaveOut string) *bed {
|
||||
b.buckets[marksBucket] = kv
|
||||
}
|
||||
// The Go build seat's work queue, as the broker derives it from the seat's accepted kinds (delivery.AskStream).
|
||||
seat, _ := delivery.AskStream(delivery.AskGo)
|
||||
seat, _ := buildstep.AskStream(buildstep.AskGo)
|
||||
if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: seat, Subjects: []string{"mesh.seat.node-build-go.accept.>"},
|
||||
Retention: jetstream.WorkQueuePolicy}); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -386,7 +387,7 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) {
|
||||
firstViewBound, firstViewWait = 300*time.Millisecond, 50*time.Millisecond
|
||||
t.Cleanup(func() { indexerLate, firstViewBound, firstViewWait = nil, 0, 0 })
|
||||
for _, name := range append(append([]string{}, readBuckets...), watched...) {
|
||||
if strings.HasPrefix(name, delivery.IndexerModule+"_") {
|
||||
if strings.HasPrefix(name, meshcatalogclient.Module+"_") {
|
||||
t.Errorf("the assigner reads the indexer's state %s itself", name)
|
||||
}
|
||||
}
|
||||
@@ -426,10 +427,10 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) {
|
||||
"seat-holders": {"n1.node-tools"},
|
||||
"wants": {"n1.mesh-grants"},
|
||||
})
|
||||
graphKey := meshconditionsclient.Key(meshconditionsclient.ScopeModule, delivery.AssignerModule+"."+delivery.IndexerModule+"."+graph.State, views.UnansweredKind)
|
||||
graphKey := meshconditionsclient.Key(meshconditionsclient.ScopeModule, mmac.Module+"."+meshcatalogclient.Module+"."+graph.State, views.UnansweredKind)
|
||||
graphRaised := func() bool {
|
||||
e, err := b.buckets[assign.FindingsBucket].Get(b.ctx, graphKey)
|
||||
return err == nil && strings.Contains(string(e.Value()), delivery.IndexerModule+".graph")
|
||||
return err == nil && strings.Contains(string(e.Value()), meshcatalogclient.Module+".graph")
|
||||
}
|
||||
for deadline := time.Now().Add(10 * time.Second); !graphRaised(); time.Sleep(50 * time.Millisecond) {
|
||||
if time.Now().After(deadline) {
|
||||
@@ -898,7 +899,7 @@ func (b *bed) answer(t *testing.T, key, option string) {
|
||||
// answerTo is answer to the ask with this id (the router's warrant names it).
|
||||
func (b *bed) answerTo(t *testing.T, key, option, askID string) {
|
||||
t.Helper()
|
||||
v, err := delivery.EncodeAnswer(delivery.Answer{Option: option, Warrant: askID + "@2026-10-24T12:00:00Z", Words: "the operator"})
|
||||
v, err := meshdeliveryclient.EncodeAnswer(meshdeliveryclient.Answer{Option: option, Warrant: askID + "@2026-10-24T12:00:00Z", Words: "the operator"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1091,7 +1092,7 @@ func (s bedStore) kv(state string) jetstream.KeyValue {
|
||||
if strings.Contains(state, ".") {
|
||||
return s.b.buckets[strings.Replace(state, ".", "_", 1)]
|
||||
}
|
||||
return s.b.buckets[delivery.AssignerModule+"_"+state]
|
||||
return s.b.buckets[mmac.Module+"_"+state]
|
||||
}
|
||||
|
||||
func (s bedStore) get(state, key string) ([]byte, uint64, bool, error) {
|
||||
@@ -1126,7 +1127,7 @@ func (s bedStore) history(string, string) ([]stdio.StateRevision, error) { retur
|
||||
// and declined, writes nothing and is withdrawn.
|
||||
func TestAProposalIsAnsweredApprovedAndWritten(t *testing.T) {
|
||||
b := startBed(t, "")
|
||||
if _, err := b.js.CreateStream(b.ctx, jetstream.StreamConfig{Name: "MOD_" + delivery.AssignerModule + "_placement",
|
||||
if _, err := b.js.CreateStream(b.ctx, jetstream.StreamConfig{Name: "MOD_" + mmac.Module + "_placement",
|
||||
Subjects: placementSubjects()}); err != nil { // the seat's four events: the views family has a stream of its own
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1136,7 +1137,7 @@ func TestAProposalIsAnsweredApprovedAndWritten(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(nc.Close)
|
||||
if _, err := nc.Subscribe(process.ModuleStreamSubject(delivery.AssignerModule, mma.EventPlacementChanged), func(m *nats.Msg) {
|
||||
if _, err := nc.Subscribe(process.ModuleStreamSubject(mmac.Module, mma.EventPlacementChanged), func(m *nats.Msg) {
|
||||
var e mma.PlacementEvent
|
||||
if json.Unmarshal(m.Data, &e) == nil {
|
||||
heard <- e
|
||||
@@ -1310,7 +1311,7 @@ func TestAProposalIsAnsweredApprovedAndWritten(t *testing.T) {
|
||||
}
|
||||
silent := q.(proposed).Proposal
|
||||
decided := proposalNow(silent.ID, "decided without its silent nodes", func(p mma.Proposal) bool { return p.State == mmac.ProposalAsked })
|
||||
if decided.Verdict == nil || decided.Verdict.State != delivery.VerdictPass ||
|
||||
if decided.Verdict == nil || decided.Verdict.State != mdcc.VerdictPass ||
|
||||
!strings.Contains(strings.Join(decided.Verdict.Notes, "; "), "no answer from") || !strings.Contains(strings.Join(decided.Verdict.Notes, "; "), "laptop (offline)") {
|
||||
t.Errorf("the silent node's verdict = %+v", decided.Verdict)
|
||||
}
|
||||
@@ -1378,8 +1379,8 @@ func (b *bed) viewsHold(t *testing.T, state, key string) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for deadline := time.Now().Add(20 * time.Second); ; time.Sleep(50 * time.Millisecond) {
|
||||
f := &views.Follower{Owner: delivery.AssignerModule, Tool: state, State: state, Ask: func(context.Context, string) (views.Answer, error) {
|
||||
return views.FirstView(delivery.AssignerModule, state, src(kv), src(marks), "", time.Now())
|
||||
f := &views.Follower{Owner: mmac.Module, Tool: state, State: state, Ask: func(context.Context, string) (views.Answer, error) {
|
||||
return views.FirstView(mmac.Module, state, src(kv), src(marks), "", time.Now())
|
||||
}}
|
||||
if err := f.Start(b.ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1388,7 +1389,7 @@ func (b *bed) viewsHold(t *testing.T, state, key string) {
|
||||
gap := false
|
||||
for seq := info.State.FirstSeq; seq > 0 && seq <= info.State.LastSeq; seq++ {
|
||||
m, err := st.GetMsg(b.ctx, seq)
|
||||
if owner, _ := views.OwnerOfEvent(m.Subject); err != nil || owner != delivery.AssignerModule || views.StateOfEvent(m.Subject) != state {
|
||||
if owner, _ := views.OwnerOfEvent(m.Subject); err != nil || owner != mmac.Module || views.StateOfEvent(m.Subject) != state {
|
||||
continue
|
||||
}
|
||||
e, err := views.DecodeEvent(m.Data)
|
||||
@@ -1446,7 +1447,7 @@ func (s bedSource) Get(key string) (*views.Entry, bool, error) {
|
||||
func placementSubjects() []string {
|
||||
var out []string
|
||||
for _, e := range mma.Events() {
|
||||
out = append(out, process.ModuleStreamSubject(delivery.AssignerModule, e))
|
||||
out = append(out, process.ModuleStreamSubject(mmac.Module, e))
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -1460,11 +1461,11 @@ var indexerLate chan struct{}
|
||||
// read by the assigner's durable consumer; and its first-view tools of the three answered from the buckets at their marks.
|
||||
func serveIndexer(t *testing.T, b *bed, nc *nats.Conn) {
|
||||
t.Helper()
|
||||
marks, err := b.js.CreateKeyValue(b.ctx, jetstream.KeyValueConfig{Bucket: delivery.IndexerModule + "_" + views.MarksState, History: 1})
|
||||
marks, err := b.js.CreateKeyValue(b.ctx, jetstream.KeyValueConfig{Bucket: meshcatalogclient.Module + "_" + views.MarksState, History: 1})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
em := views.Emitter{Owner: delivery.IndexerModule, Subject: process.Account{Node: "n1", Module: delivery.IndexerModule}.EventSubject,
|
||||
em := views.Emitter{Owner: meshcatalogclient.Module, Subject: process.Account{Node: "n1", Module: meshcatalogclient.Module}.EventSubject,
|
||||
Publish: views.JetStreamPublish(b.js), Marks: marks}
|
||||
for state, bucket := range indexerFirstViews {
|
||||
kv, err := b.js.CreateKeyValue(b.ctx, jetstream.KeyValueConfig{Bucket: bucket, History: 5})
|
||||
@@ -1489,7 +1490,7 @@ func serveIndexer(t *testing.T, b *bed, nc *nats.Conn) {
|
||||
After string `json:"after"`
|
||||
}
|
||||
_ = json.Unmarshal(m.Data, &args)
|
||||
a, err := views.FirstView(delivery.IndexerModule, state, bedSource{b.ctx, kv}, bedSource{b.ctx, marks}, args.After, time.Now())
|
||||
a, err := views.FirstView(meshcatalogclient.Module, state, bedSource{b.ctx, kv}, bedSource{b.ctx, marks}, args.After, time.Now())
|
||||
out := map[string]any{"result": a, "node": "n0"}
|
||||
if err != nil {
|
||||
out = map[string]any{"error": err.Error()}
|
||||
@@ -1549,7 +1550,7 @@ func firstViewsBeforeAnyNewFormState(t *testing.T, b *bed, granted map[string][]
|
||||
outR, outW := io.Pipe()
|
||||
t.Cleanup(func() { inW.Close(); outW.Close() })
|
||||
go func() {
|
||||
_ = stdio.ServeOn(delivery.AssignerModule, viewTools(func(k string) string { return env[k] }, state, time.Now), inR, outW)
|
||||
_ = stdio.ServeOn(mmac.Module, viewTools(func(k string) string { return env[k] }, state, time.Now), inR, outW)
|
||||
}()
|
||||
answers := make(chan map[string]any, 16)
|
||||
go func() {
|
||||
@@ -1570,7 +1571,7 @@ func firstViewsBeforeAnyNewFormState(t *testing.T, b *bed, granted map[string][]
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(nc.Close)
|
||||
sub, err := nc.Subscribe("mesh.mod."+delivery.AssignerModule+".call.*.*", func(msg *nats.Msg) {
|
||||
sub, err := nc.Subscribe("mesh.mod."+mmac.Module+".call.*.*", func(msg *nats.Msg) {
|
||||
one <- struct{}{}
|
||||
defer func() { <-one }()
|
||||
tokens := strings.Split(msg.Subject, ".")
|
||||
@@ -1602,7 +1603,7 @@ func firstViewsBeforeAnyNewFormState(t *testing.T, b *bed, granted map[string][]
|
||||
ask := func(user, tool string) (views.Answer, error) {
|
||||
return views.AskVia(func(key string, body any) (json.RawMessage, error) {
|
||||
data, _ := json.Marshal(body)
|
||||
msg, err := nc.Request("mesh.mod."+delivery.AssignerModule+".call."+tool+"."+strings.ReplaceAll(user, ".", "~"), data, 5*time.Second)
|
||||
msg, err := nc.Request("mesh.mod."+mmac.Module+".call."+tool+"."+strings.ReplaceAll(user, ".", "~"), data, 5*time.Second)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1618,7 +1619,7 @@ func firstViewsBeforeAnyNewFormState(t *testing.T, b *bed, granted map[string][]
|
||||
t.Errorf("%s's first view of %s before any new-form state: %v", user, tool, err)
|
||||
case slices.Contains(allowed, user):
|
||||
keys, _ := b.buckets[viewedStates[tool]].Keys(b.ctx)
|
||||
if a.Owner != delivery.AssignerModule || a.State != tool || len(a.Values) != len(keys) {
|
||||
if a.Owner != mmac.Module || a.State != tool || len(a.Values) != len(keys) {
|
||||
t.Errorf("%s's first view of %s = %+v, the state holds %v", user, tool, a, keys)
|
||||
}
|
||||
case err == nil || !strings.Contains(err.Error(), "refused"):
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"io"
|
||||
"log"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
@@ -26,7 +27,6 @@ import (
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
||||
@@ -85,7 +85,7 @@ var ownBuckets = []string{buckets.Asks, buckets.Differences,
|
||||
const engineReadsState = "engine-reads"
|
||||
|
||||
// engineReadsBucket is that state's bucket.
|
||||
const engineReadsBucket = delivery.AssignerModule + "_" + engineReadsState
|
||||
const engineReadsBucket = mmac.Module + "_" + engineReadsState
|
||||
|
||||
// seatBuckets are the seat's states, new with it: until the controller has made them from the manifest and the bus grants
|
||||
// them, the assigner starts without them and binds each once the bus says it was created (issue 1790's kind).
|
||||
@@ -512,7 +512,7 @@ var PutsReopenEvery = time.Minute
|
||||
// (ADR 0437 clause 9).
|
||||
func sayVia(ctx context.Context, js jetstream.JetStream) func(oc.Condition) error {
|
||||
return func(c oc.Condition) error {
|
||||
subject, err := occ.ConditionSubject(delivery.AssignerModule)
|
||||
subject, err := occ.ConditionSubject(mmac.Module)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -529,7 +529,7 @@ func sayVia(ctx context.Context, js jetstream.JetStream) func(oc.Condition) erro
|
||||
// consumer on EVENTS, and asks the node it names again; the hub also hands the indexer's views to the followers of
|
||||
// indexerViews, and starts once both are registered.
|
||||
func hearReadsChanged(ctx context.Context, js jetstream.JetStream, hub *process.EventHub, reads *enginereads.Keeper, findings assign.Findings, logf func(string, ...any)) {
|
||||
account := process.Account{Node: thisNode, Module: delivery.AssignerModule}
|
||||
account := process.Account{Node: thisNode, Module: mmac.Module}
|
||||
w := notHeardWriter(findings, logf)
|
||||
handle := func(m jetstream.Msg) {
|
||||
if err := m.Ack(); err != nil {
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
|
||||
"git.novox.be/novox/mesh-networking/modules/mesh-wireguard/go/overlay"
|
||||
"git.novox.be/novox/mesh-sdk/go/motion"
|
||||
"maps"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"slices"
|
||||
@@ -18,7 +20,6 @@ import (
|
||||
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||
@@ -1008,7 +1009,7 @@ func (p *passer) provisionFindings(failed map[string]provisions.Provision) {
|
||||
|
||||
// MissingBound is how long a required provision may have no key before it is said: a module's delivery bound, the default
|
||||
// when its manifest names none (ADR 0564 clause 13 (d)).
|
||||
var MissingBound = delivery.DefaultDeliveryBound
|
||||
var MissingBound = motion.DefaultDeliveryBound
|
||||
|
||||
// missingPulse is the pulse key of a provision with no key, `provision-missing.<node>.<module>.<provision>`.
|
||||
func missingPulse(key string) string { return "provision-missing." + key }
|
||||
@@ -1150,8 +1151,8 @@ func offered(manifests map[string]catalogue.Manifest) func(string) bool {
|
||||
for _, m := range manifests {
|
||||
add(m)
|
||||
}
|
||||
for _, module := range delivery.ProvidedModules() {
|
||||
if m, _, err := delivery.ProvidedManifest(module); err == nil {
|
||||
for _, module := range overlay.ProvidedModules() {
|
||||
if m, _, err := overlay.ProvidedManifest(module); err == nil {
|
||||
add(m)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@ import (
|
||||
watchdogs "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs"
|
||||
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
mdseat "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdelivery"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
|
||||
@@ -29,7 +31,6 @@ import (
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/busretry"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||
@@ -150,7 +151,7 @@ func TestAnAnswerCountsOnlyForTheAskingItAnswered(t *testing.T) {
|
||||
return mustAskID(a)
|
||||
}
|
||||
first := put(100)
|
||||
v, _ := delivery.EncodeAnswer(delivery.Answer{Option: "release", Warrant: first + "@2026-10-25T01:00:00Z", Words: "the operator"})
|
||||
v, _ := mdc.EncodeAnswer(mdc.Answer{Option: "release", Warrant: first + "@2026-10-25T01:00:00Z", Words: "the operator"})
|
||||
p.w.put(buckets.Answers, key, v)
|
||||
if !p.answeredWith(key, "release") {
|
||||
t.Fatal("the answer to the ask that stands is not taken")
|
||||
@@ -362,7 +363,7 @@ func putOfTheBus(t *testing.T) {
|
||||
buildKV.values[bkey] = built
|
||||
modules := mem()
|
||||
modules.values["nats"] = mod
|
||||
s := newPutTools(memStore{putsState: putsKV, builds.BuilderModule + ".builds": buildKV, delivery.IndexerModule + ".modules": modules})
|
||||
s := newPutTools(memStore{putsState: putsKV, builds.BuilderModule + ".builds": buildKV, meshcatalogclient.Module + ".modules": modules})
|
||||
s.now = func() time.Time { return now }
|
||||
was := answerWithin
|
||||
answerWithin = 0
|
||||
@@ -419,7 +420,7 @@ func putOfTheBus(t *testing.T) {
|
||||
t.Fatal("the bus's want was written before the operator's warrant")
|
||||
}
|
||||
world(buckets.Asks, akey, asksKV.values[akey])
|
||||
yes, _ := delivery.EncodeAnswer(delivery.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-25T22:01:00Z", Words: "the operator, verified"})
|
||||
yes, _ := mdc.EncodeAnswer(mdc.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-25T22:01:00Z", Words: "the operator, verified"})
|
||||
world(buckets.Answers, akey, yes)
|
||||
if got := step(); got.Step != puts.Snapshot {
|
||||
t.Fatalf("on the warrant the put stands at %s: %s", got.Step, got.Words)
|
||||
@@ -465,7 +466,7 @@ func putOfTheBus(t *testing.T) {
|
||||
t.Fatalf("put again, it stands at %s (%s); its ask %q, %v; the first ask was %q", again.Step, again.Words, a2.Ask.ID, err, a.Ask.ID)
|
||||
}
|
||||
world(buckets.Asks, akey, asksKV.values[akey])
|
||||
yes2, _ := delivery.EncodeAnswer(delivery.Answer{Option: assign.OptionYes, Warrant: a2.Ask.ID + "@2026-10-25T22:03:00Z", Words: "the operator, verified"})
|
||||
yes2, _ := mdc.EncodeAnswer(mdc.Answer{Option: assign.OptionYes, Warrant: a2.Ask.ID + "@2026-10-25T22:03:00Z", Words: "the operator, verified"})
|
||||
world(buckets.Answers, akey, yes2)
|
||||
if got := step(); got.Step != puts.Snapshot {
|
||||
t.Fatalf("on the second warrant the put stands at %s: %s", got.Step, got.Words)
|
||||
@@ -934,19 +935,19 @@ func aReleasesApproveAnswersTheMoveOfItsBuildAlone(t *testing.T) {
|
||||
p.logf = t.Logf
|
||||
mod, _ := meshcatalogclient.EncodeModule(meshcatalog.ModulesByModuleValue{Fp2: fpTest, Repository: "novox/web", Commit: commit, Src: 7, FpSrc: c.fpSrc, Path: meshcatalogclient.RootPath})
|
||||
p.w.put(buckets.Modules, "web", mod)
|
||||
src, _ := delivery.EncodeSource(delivery.Source{Group: "feat/web", Heads: map[string]string{"novox/web": commit}})
|
||||
p.w.putEntry(buckets.Source, delivery.SourceMainKey, src, 7, time.Now())
|
||||
later, _ := delivery.EncodeSource(delivery.Source{Group: "feat/other", Heads: map[string]string{"novox/web": commit, "novox/x": commit}})
|
||||
p.w.putEntry(buckets.Source, delivery.SourceMainKey, later, 8, time.Now()) // a later merge leaves revision 7's release
|
||||
src, _ := mdc.EncodeSource(mdseat.SourceByMainValue{Group: "feat/web", Heads: map[string]string{"novox/web": commit}})
|
||||
p.w.putEntry(buckets.Source, mdc.SourceMainKey, src, 7, time.Now())
|
||||
later, _ := mdc.EncodeSource(mdseat.SourceByMainValue{Group: "feat/other", Heads: map[string]string{"novox/web": commit, "novox/x": commit}})
|
||||
p.w.putEntry(buckets.Source, mdc.SourceMainKey, later, 8, time.Now()) // a later merge leaves revision 7's release
|
||||
if c.mergedAt != "" {
|
||||
merge, err := delivery.EncodeMerge(delivery.Merge{Group: "feat/web", Ask: "merge.feat_web.0123456789ab", Pulls: []delivery.MergePull{
|
||||
{Head: delivery.Head{Repository: "novox/web", Number: 3, Head: strings.Repeat("3", 40)}, State: delivery.MergeMerged, Commit: c.mergedAt}}})
|
||||
merge, err := mdc.EncodeMerge(mdseat.MergesByGroupValue{Group: "feat/web", Ask: "merge.feat_web.0123456789ab", Pulls: []mdseat.MergesByGroupValuePullsItem{
|
||||
{Repository: "novox/web", Number: 3, Head: strings.Repeat("3", 40), State: string(mdc.MergeMerged), Commit: c.mergedAt}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.w.put(buckets.Merges, "feat/web", merge)
|
||||
other, err := delivery.EncodeMerge(delivery.Merge{Group: "feat/other", Ask: "merge.feat_other.0123456789ab", Pulls: []delivery.MergePull{
|
||||
{Head: delivery.Head{Repository: "novox/x", Number: 4, Head: strings.Repeat("4", 40)}, State: delivery.MergeMerged, Commit: commit}}})
|
||||
other, err := mdc.EncodeMerge(mdseat.MergesByGroupValue{Group: "feat/other", Ask: "merge.feat_other.0123456789ab", Pulls: []mdseat.MergesByGroupValuePullsItem{
|
||||
{Repository: "novox/x", Number: 4, Head: strings.Repeat("4", 40), State: string(mdc.MergeMerged), Commit: commit}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1058,7 +1059,7 @@ func aPlacedNodesWantsNameTheBuildAloneAndItsYesComesFromItsHave(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
put(buckets.Asks, akey, asksKV.values[akey])
|
||||
yes, _ := delivery.EncodeAnswer(delivery.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-26T19:00:00Z", Words: "the operator"})
|
||||
yes, _ := mdc.EncodeAnswer(mdc.Answer{Option: assign.OptionYes, Warrant: a.Ask.ID + "@2026-10-26T19:00:00Z", Words: "the operator"})
|
||||
put(buckets.Answers, akey, yes)
|
||||
p.wants(context.Background())
|
||||
sync()
|
||||
@@ -1085,7 +1086,7 @@ func TestAnApprovedPlacementCallsNoControllerVerb(t *testing.T) {
|
||||
p.publish = func(event string, _ any, _ string) error { said = append(said, event); return nil }
|
||||
prop := mma.Proposal{ID: "p-one", By: "operator@laptop", Why: "move web"}
|
||||
change := plc.ChangeOf(mma.Placement{Node: "anchor"}, mma.Placement{Node: "anchor", Modules: []mma.PlacedModule{{Module: "web"}}})
|
||||
p.followWrite(prop, delivery.Answer{}, []plc.Change{change})
|
||||
p.followWrite(prop, mdc.Answer{}, []plc.Change{change})
|
||||
if len(bus.calls) != 0 || !slices.Equal(said, []string{mma.EventPlacementChanged}) {
|
||||
t.Fatalf("calls = %d, said = %v", len(bus.calls), said)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"mesh-delivery-assigner/internal/assign"
|
||||
)
|
||||
@@ -408,7 +407,7 @@ func (a *putActs) warrant(id, ask string) {
|
||||
a.warranted[id] = true
|
||||
a.mu.Unlock()
|
||||
go func() {
|
||||
if _, err := a.rec.RecordWarrant(delivery.TellerModule, ask); err != nil {
|
||||
if _, err := a.rec.RecordWarrant(buckets.TellerModule, ask); err != nil {
|
||||
a.logf("the put's warrant %s is not recorded in the hand-act log: %v", ask, err)
|
||||
a.mu.Lock()
|
||||
a.warrantNo[id] = fmt.Sprintf("the warrant %s is not recorded in the hand-act log: %v", ask, err)
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
|
||||
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"maps"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
@@ -24,7 +26,6 @@ import (
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
|
||||
"mesh-delivery-assigner/internal/assign"
|
||||
@@ -51,9 +52,9 @@ func streamPublisher(ctx context.Context, js jetstream.JetStream, node string) p
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
msg := nats.NewMsg(process.ModuleStreamSubject(delivery.AssignerModule, event))
|
||||
msg := nats.NewMsg(process.ModuleStreamSubject(mmac.Module, event))
|
||||
msg.Header.Set("x-event-id", id)
|
||||
msg.Header.Set("x-source", delivery.AssignerModule)
|
||||
msg.Header.Set("x-source", mmac.Module)
|
||||
msg.Header.Set("x-node", node)
|
||||
msg.Header.Set("x-time", time.Now().UTC().Format(time.RFC3339Nano))
|
||||
msg.Header.Set("content-type", "application/json")
|
||||
@@ -86,7 +87,7 @@ func (a *seatActs) record(warrant string) {
|
||||
}
|
||||
ask, _, _ := strings.Cut(warrant, "@")
|
||||
go func() {
|
||||
if taken, err := a.rec.RecordWarrant(delivery.TellerModule, ask); err != nil {
|
||||
if taken, err := a.rec.RecordWarrant(buckets.TellerModule, ask); err != nil {
|
||||
a.logf("the placement's warrant %s is not recorded in the hand-act log: %v", ask, err)
|
||||
} else {
|
||||
a.logf("the placement's warrant %s is recorded in the log of %s", ask, taken.Log)
|
||||
@@ -328,11 +329,11 @@ func (p *passer) stepProposal(ctx context.Context, prop mma.Proposal, rev uint64
|
||||
}
|
||||
prop.Verdict = &v
|
||||
switch v.State {
|
||||
case delivery.VerdictFail:
|
||||
case mdcc.VerdictFail:
|
||||
prop.State, prop.Ask = mmac.ProposalFailed, ""
|
||||
case plc.VerdictWaits:
|
||||
prop.State, prop.Ask = mmac.ProposalAnswering, ""
|
||||
case delivery.VerdictPass:
|
||||
case mdcc.VerdictPass:
|
||||
if prop.State != mmac.ProposalAsked || again {
|
||||
var ok bool
|
||||
if prop, ok = p.ask(ctx, prop, akey, judge.Brief(prop, v)); !ok {
|
||||
@@ -558,7 +559,7 @@ func (p *passer) addNode(ctx context.Context, prop mma.Proposal, revs map[string
|
||||
_ = p.kvs[plc.ProposalsBucket].Delete(ctx, prop.ID)
|
||||
p.w.put(plc.ProposalsBucket, prop.ID, nil)
|
||||
w := prop.Warrant
|
||||
p.sayChanged(prop, delivery.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
|
||||
p.sayChanged(prop, mdc.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
|
||||
Words: fmt.Sprintf("the operator approved the machine %s at %s through the enrolment's ask %s", w.Node, w.Address, w.Ask)},
|
||||
[]plc.Change{c})
|
||||
}
|
||||
@@ -585,14 +586,14 @@ func (p *passer) removeNode(ctx context.Context, prop mma.Proposal, current map[
|
||||
_ = p.kvs[plc.ProposalsBucket].Delete(ctx, prop.ID)
|
||||
p.w.put(plc.ProposalsBucket, prop.ID, nil)
|
||||
w := prop.Warrant
|
||||
p.sayChanged(prop, delivery.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
|
||||
p.sayChanged(prop, mdc.Answer{Option: assign.OptionYes, Warrant: w.Warrant,
|
||||
Words: fmt.Sprintf("the machine %s left placement: its enrolment (ask %s) ended before it confirmed", w.Node, w.Ask)},
|
||||
[]plc.Change{c})
|
||||
}
|
||||
|
||||
// followWrite follows the keys a warrant wrote: the warrant recorded and placement-changed said. No verb of the
|
||||
// controller is called: the placement is the one source of where modules run (ADR 0567 §8, issue 774).
|
||||
func (p *passer) followWrite(prop mma.Proposal, answer delivery.Answer, changes []plc.Change) {
|
||||
func (p *passer) followWrite(prop mma.Proposal, answer mdc.Answer, changes []plc.Change) {
|
||||
if len(changes) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -610,7 +611,7 @@ func sortedNodes(m map[string]*mma.Placement) []string {
|
||||
}
|
||||
|
||||
// sayChanged says placement-changed for the keys written.
|
||||
func (p *passer) sayChanged(prop mma.Proposal, answer delivery.Answer, changes []plc.Change) {
|
||||
func (p *passer) sayChanged(prop mma.Proposal, answer mdc.Answer, changes []plc.Change) {
|
||||
if len(changes) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"mesh-delivery-assigner/internal/assign"
|
||||
plc "mesh-delivery-assigner/internal/placement"
|
||||
@@ -43,7 +42,7 @@ func (runtimeStore) history(state, key string) ([]stdio.StateRevision, error) {
|
||||
// The states the verbs read, as the runtime names them: the seat's own by their local names, the others'
|
||||
// `<module>.<state>`.
|
||||
const (
|
||||
modulesState = delivery.IndexerModule + ".modules"
|
||||
modulesState = meshcatalogclient.Module + ".modules"
|
||||
haveState = "node-engine.have"
|
||||
)
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"time"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||
)
|
||||
@@ -77,7 +76,7 @@ func (s *putTools) version(module, version string) (string, error) {
|
||||
v := strings.ToLower(strings.TrimSpace(version))
|
||||
switch {
|
||||
case v == "newest":
|
||||
raw, _, found, err := s.st.get(delivery.IndexerModule+".modules", module)
|
||||
raw, _, found, err := s.st.get(meshcatalogclient.ModulesRead, module)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("the indexer's modules cannot be read: %w", err)
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"slices"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||
|
||||
@@ -66,7 +64,7 @@ func (p *passer) served(ctx context.Context, get getter, g graph.Graph, n assign
|
||||
if len(g) == 0 {
|
||||
return nil
|
||||
}
|
||||
served, unread := graph.Served(graphHaves(n.Haves), func(module, fp string) ([]string, bool) { return p.servesOf(ctx, get, module, fp) },
|
||||
served, unread := graph.Served(n.Haves, func(module, fp string) ([]string, bool) { return p.servesOf(ctx, get, module, fp) },
|
||||
func(module string) []string { return g[module].Serves })
|
||||
if len(unread) > 0 {
|
||||
p.logf("the manifest of the running build of %v cannot be read, so what the module graph says they serve is counted as served", unread)
|
||||
@@ -130,16 +128,3 @@ func (p *passer) manifestOf(ctx context.Context, get getter, module, fp string)
|
||||
}
|
||||
return got.manifest, true
|
||||
}
|
||||
|
||||
// graphHaves is the haves as the module graph's Served reads them, which keeps the earlier have form for what it reads: the
|
||||
// build, the phase and the health of each module on each node.
|
||||
func graphHaves(haves map[string]map[string]nodeengine.HaveByNodeModuleValue) map[string]map[string]delivery.Have {
|
||||
out := map[string]map[string]delivery.Have{}
|
||||
for node, modules := range haves {
|
||||
out[node] = map[string]delivery.Have{}
|
||||
for module, h := range modules {
|
||||
out[node][module] = delivery.Have{FP: h.Fp, Build: h.Build, Phase: delivery.Phase(h.Phase), Health: delivery.Health(h.Health)}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"slices"
|
||||
"time"
|
||||
@@ -12,7 +14,6 @@ import (
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
|
||||
@@ -27,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
// marksBucket is the assigner's state of what its views family said each state up to.
|
||||
var marksBucket = delivery.AssignerModule + "_" + views.MarksState
|
||||
var marksBucket = mmac.Module + "_" + views.MarksState
|
||||
|
||||
// viewedTool is one tool over one state of the assigner's.
|
||||
type viewedTool struct{ tool, state, words string }
|
||||
@@ -66,13 +67,13 @@ func viewTools(getenv func(string) string, state func(string) views.Source, now
|
||||
marks := state(views.MarksState)
|
||||
var out []stdio.Tool
|
||||
for _, t := range firstViewTools {
|
||||
out = append(out, views.FirstViewTool(delivery.AssignerModule, t.tool, t.state, t.words, views.ParseCallers(getenv(views.CallersEnv(t.tool))), state(t.state), marks, now))
|
||||
out = append(out, views.FirstViewTool(mmac.Module, t.tool, t.state, t.words, views.ParseCallers(getenv(views.CallersEnv(t.tool))), state(t.state), marks, now))
|
||||
}
|
||||
for _, t := range readTools {
|
||||
out = append(out, views.ReadTool(delivery.AssignerModule, t.tool, t.state, t.words, state(t.state), marks, now))
|
||||
out = append(out, views.ReadTool(mmac.Module, t.tool, t.state, t.words, state(t.state), marks, now))
|
||||
}
|
||||
// Its own first views, of the indexer's manifests, modules and graph (DLV-F3r, ADR 0631 §2): read, and asked again by hand.
|
||||
return append(out, views.StatusTools(delivery.AssignerModule, "assigner_first_views", "assigner_first_view_again", stdio.State(views.StatusState), meshhandactsclient.Recorder{Ask: stdio.Ask}, now)...)
|
||||
return append(out, views.StatusTools(mmac.Module, "assigner_first_views", "assigner_first_view_again", stdio.State(views.StatusState), meshhandactsclient.Recorder{Ask: stdio.Ask}, now)...)
|
||||
}
|
||||
|
||||
func keptSource(name string) views.Source { return views.KeptSource{State: stdio.State(name)} }
|
||||
@@ -84,7 +85,7 @@ func startViews(ctx context.Context, js jetstream.JetStream, nc process.Subscrib
|
||||
if findings.Put == nil {
|
||||
return
|
||||
}
|
||||
if err := viewFindings(findings).Put(views.TooLargeFinding(delivery.AssignerModule, state, key, size, time.Now())); err != nil {
|
||||
if err := viewFindings(findings).Put(views.TooLargeFinding(mmac.Module, state, key, size, time.Now())); err != nil {
|
||||
logf("views: the finding of %s.%s too large is not written: %v", state, key, err)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +110,7 @@ func startViews(ctx context.Context, js jetstream.JetStream, nc process.Subscrib
|
||||
// viewsEmitter is the assigner's emitter of its views family: a change not said past views.Bound is its finding
|
||||
// view-unsaid, in its findings (review round 2); with no findings state it is said in the log only.
|
||||
func viewsEmitter(js jetstream.JetStream, account process.Account, mk jetstream.KeyValue, findings assign.Findings, tooLarge func(string, string, int), logf func(string, ...any)) views.Emitter {
|
||||
em := views.Emitter{Owner: delivery.AssignerModule, Subject: account.EventSubject, Publish: views.JetStreamPublish(js), Marks: mk, TooLarge: tooLarge, Logf: logf}
|
||||
em := views.Emitter{Owner: mmac.Module, Subject: account.EventSubject, Publish: views.JetStreamPublish(js), Marks: mk, TooLarge: tooLarge, Logf: logf}
|
||||
if findings.Put != nil && findings.Delete != nil {
|
||||
em.Findings = viewFindings(findings)
|
||||
}
|
||||
@@ -122,7 +123,7 @@ func viewFindings(f assign.Findings) views.FindingWriter {
|
||||
}
|
||||
|
||||
// firstViewsBucket is the assigner's own state of its first views (views.StatusState).
|
||||
var firstViewsBucket = delivery.AssignerModule + "_" + views.StatusState
|
||||
var firstViewsBucket = mmac.Module + "_" + views.StatusState
|
||||
|
||||
// indexerViews are the assigner's first views of the indexer's manifests, modules and module graph (ADR 0615 §1,
|
||||
// ADR 0621 §2, ADR 0631; DLV-F2r): asked at the start through the indexer's tools, then followed on indexer-views, asking once more on a gap;
|
||||
@@ -154,7 +155,7 @@ func (iv *indexerViews) start(ctx context.Context, w *world, wake func(), settle
|
||||
if iv.findings.Put == nil {
|
||||
return
|
||||
}
|
||||
f := views.UnansweredFinding(delivery.AssignerModule, s, time.Now())
|
||||
f := views.UnansweredFinding(mmac.Module, s, time.Now())
|
||||
var err error
|
||||
if raised {
|
||||
err = viewFindings(iv.findings).Put(f)
|
||||
@@ -169,8 +170,8 @@ func (iv *indexerViews) start(ctx context.Context, w *world, wake func(), settle
|
||||
var all []*views.Follower
|
||||
for state, bucket := range indexerFirstViews {
|
||||
bucket := bucket
|
||||
tool := delivery.IndexerModule + "." + state
|
||||
f := &views.Follower{Owner: delivery.IndexerModule, Tool: tool, State: state, Ask: views.AskVia(iv.call, tool), Logf: iv.logf,
|
||||
tool := meshcatalogclient.Module + "." + state
|
||||
f := &views.Follower{Owner: meshcatalogclient.Module, Tool: tool, State: state, Ask: views.AskVia(iv.call, tool), Logf: iv.logf,
|
||||
Bound: firstViewBound, Wait: firstViewWait,
|
||||
Raise: func(s views.Status) { finding(s, true) }, Clear: func(s views.Status) { finding(s, false) },
|
||||
Changed: func(key string, value json.RawMessage, deleted bool, at time.Time) {
|
||||
@@ -201,7 +202,7 @@ func (iv *indexerViews) start(ctx context.Context, w *world, wake func(), settle
|
||||
// Not heard, the indexer's views family is the finding family-not-heard until it binds (ADR 0615 §5): the handler is
|
||||
// registered on the module's hub, which the assigner starts once every handler is.
|
||||
_ = notHeardWriter(iv.findings, iv.logf).Bind(process.EventsStream, "the indexer's manifests, modules and graph are the first views' alone until the assigner starts again", func() error {
|
||||
return iv.hub.Handle("mesh.mod."+delivery.IndexerModule+".event."+views.EventPrefix+"*", views.Hear(ctx, followers, iv.logf))
|
||||
return iv.hub.Handle("mesh.mod."+meshcatalogclient.Module+".event."+views.EventPrefix+"*", views.Hear(ctx, followers, iv.logf))
|
||||
})
|
||||
return len(all)
|
||||
}
|
||||
@@ -209,7 +210,7 @@ func (iv *indexerViews) start(ctx context.Context, w *world, wake func(), settle
|
||||
// notHeardWriter writes the assigner's finding of a family it does not hear into its findings (heard.Writer); with no
|
||||
// findings state it is said in the log alone.
|
||||
func notHeardWriter(findings assign.Findings, logf func(string, ...any)) heard.Writer {
|
||||
w := heard.Writer{Observer: delivery.AssignerModule, Logf: logf, Put: findings.Put}
|
||||
w := heard.Writer{Observer: mmac.Module, Logf: logf, Put: findings.Put}
|
||||
if findings.Delete != nil {
|
||||
w.Delete = func(key string) error {
|
||||
if keys, err := findings.Keys(); err == nil && !slices.Contains(keys, key) {
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
|
||||
"mesh-delivery-assigner/internal/assign"
|
||||
@@ -33,7 +32,7 @@ import (
|
||||
// The states the verbs read, as the runtime names them.
|
||||
const (
|
||||
policiesState = buckets.PoliciesState
|
||||
manifestsState = delivery.IndexerModule + ".manifests"
|
||||
manifestsState = meshcatalogclient.Module + ".manifests"
|
||||
// PolicyChangedEvent is the seat's event of a person's policy set or taken back.
|
||||
PolicyChangedEvent = "policy-changed"
|
||||
// busStepCause is the cause the bus's step is recorded under in the hand-act log.
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
watchdogs "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs"
|
||||
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/trunk"
|
||||
"git.novox.be/novox/mesh-sdk/go/keys"
|
||||
"maps"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
@@ -24,16 +26,11 @@ import (
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"mesh-delivery-assigner/internal/assign"
|
||||
plc "mesh-delivery-assigner/internal/placement"
|
||||
)
|
||||
|
||||
// noModuleWords is the indexer's reason for a module of a candidate whose directory the merge preview holds no manifest
|
||||
// for (mesh-sdk delivery.CandidateNoneNoModule, which the indexer writes): the change removes the module.
|
||||
const noModuleWords = delivery.CandidateNoneNoModule
|
||||
|
||||
// world is what the assigner watched, as it stands now: every value by bucket and key, and the manifests read by
|
||||
// digest. The watches write it; a pass reads it.
|
||||
type world struct {
|
||||
@@ -88,8 +85,8 @@ func (w *world) putEntry(bucket, key string, value []byte, revision uint64, at t
|
||||
if bucket == plc.PlacementBucket {
|
||||
_, _ = w.placement.Put(key, value, revision, false) // put took it already; this is its revision
|
||||
}
|
||||
if bucket == buckets.Source && key == delivery.SourceMainKey {
|
||||
if s, err := delivery.DecodeSource(value); err == nil && s.Group != "" {
|
||||
if bucket == buckets.Source && key == mdc.SourceMainKey {
|
||||
if s, err := mdc.DecodeSource(value); err == nil && s.Group != "" {
|
||||
w.sourceGroups[revision] = s.Group
|
||||
}
|
||||
}
|
||||
@@ -108,7 +105,7 @@ func (w *world) release(module, fp string) (string, bool) {
|
||||
w.mu.Lock()
|
||||
group := w.sourceGroups[uint64(t.FpSrc)]
|
||||
w.mu.Unlock()
|
||||
key, err := delivery.MergesKey(group)
|
||||
key, err := mdc.MergesKey(group)
|
||||
if group == "" || err != nil {
|
||||
return "", false
|
||||
}
|
||||
@@ -116,12 +113,12 @@ func (w *world) release(module, fp string) (string, bool) {
|
||||
if raw == nil {
|
||||
return "", false
|
||||
}
|
||||
merge, err := delivery.DecodeMerge(raw)
|
||||
merge, err := mdc.DecodeMerge(raw)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
for _, pull := range merge.Pulls {
|
||||
if pull.State == delivery.MergeMerged && pull.Commit == t.Commit && delivery.SameRepository(pull.Repository, t.Repository) {
|
||||
if pull.State == string(mdc.MergeMerged) && pull.Commit == t.Commit && trunk.SameRepository(pull.Repository, t.Repository) {
|
||||
return group, true
|
||||
}
|
||||
}
|
||||
@@ -503,14 +500,14 @@ func (w *world) composed(node, module, fp string) (assign.ComposedDigest, bool)
|
||||
}
|
||||
|
||||
// answer is the teller's answer to the ask at key (mesh-delivery-teller_answers, the same key), and whether there is one.
|
||||
func (w *world) answer(key string) (delivery.Answer, bool) {
|
||||
func (w *world) answer(key string) (mdc.Answer, bool) {
|
||||
w.mu.Lock()
|
||||
value, ok := w.values[buckets.Answers][key]
|
||||
w.mu.Unlock()
|
||||
if !ok {
|
||||
return delivery.Answer{}, false
|
||||
return mdc.Answer{}, false
|
||||
}
|
||||
a, err := delivery.DecodeAnswer(value)
|
||||
a, err := mdc.DecodeAnswer(value)
|
||||
return a, err == nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,9 @@ import (
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
)
|
||||
|
||||
// fakeManifests is the indexer's manifests bucket in memory.
|
||||
@@ -37,15 +34,6 @@ func (f fakeManifests) get(_ context.Context, key string) ([]byte, error) {
|
||||
|
||||
func fp(c byte) string { return meshcatalogclient.SourcePrefix2 + strings.Repeat(string(c), 64) }
|
||||
|
||||
func pull(repo string, number int, modules map[string]delivery.CandidateModule) delivery.CandidatePull {
|
||||
p := delivery.CandidatePull{Head: delivery.Head{Repository: repo, Number: number, Head: strings.Repeat("3", 40)}, Fps: modules}
|
||||
for m := range modules {
|
||||
p.Modules = append(p.Modules, m)
|
||||
}
|
||||
slices.Sort(p.Modules)
|
||||
return p
|
||||
}
|
||||
|
||||
// Review round 1 (items 3 and 4): the world counts the values a key takes, so a have written again after an answer is seen.
|
||||
func theWorldCountsTheValuesAKeyTakes(t *testing.T) {
|
||||
w := newWorld()
|
||||
|
||||
@@ -64,3 +64,8 @@ require git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate v0
|
||||
replace git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate => ../mesh-delivery-view/viewstate
|
||||
|
||||
require git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient v0.0.0-00010101000000-000000000000
|
||||
|
||||
require git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient v0.0.0-00010101000000-000000000000
|
||||
replace git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient => ../../contracts/go/clients/meshdeliverycheckerclient
|
||||
|
||||
require git.novox.be/novox/mesh-networking/modules/mesh-wireguard/go v0.0.0-20261105000000-000000000000
|
||||
|
||||
@@ -2,6 +2,7 @@ package assign
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
)
|
||||
|
||||
// HoldAsk is the ask about a module's fingerprint the assigner holds, at its key (asks.HoldAskKey): keep it held or
|
||||
@@ -68,7 +68,7 @@ func RestoreAsk(key, node, module, fp, words string, now time.Time) asks.Ask {
|
||||
// words, under the assigner's own name (ADR 0437 clause 9), keyed by the held fingerprint. needsYou is true for a module holding
|
||||
// data, whose restore ask waits for the operator.
|
||||
func HeldCondition(module, fp, node, words string, raised, needsYou bool) oc.Condition {
|
||||
key := delivery.AssignerModule + ".held." + module + "." + strings.TrimPrefix(fp, meshcatalogclient.SourcePrefix2)
|
||||
key := mmac.Module + ".held." + module + "." + strings.TrimPrefix(fp, meshcatalogclient.SourcePrefix2)
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: module, Machine: node}
|
||||
if !raised {
|
||||
return oc.Condition{Key: key, Subject: subject, State: occ.StateCleared}
|
||||
@@ -91,7 +91,7 @@ func HeldCondition(module, fp, node, words string, raised, needsYou bool) oc.Con
|
||||
// the node keeps its want. It names the node, the module, fp and the have's words, keyed by node and module, and is cleared
|
||||
// (raised false) once the node no longer fails alone.
|
||||
func NodeFailedCondition(node, module, fp string, f NodeFailure, raised bool) oc.Condition {
|
||||
key := delivery.AssignerModule + ".failed-alone." + node + "." + module
|
||||
key := mmac.Module + ".failed-alone." + node + "." + module
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: module, Machine: node}
|
||||
if !raised {
|
||||
return oc.Condition{Key: key, Subject: subject, State: occ.StateCleared,
|
||||
@@ -114,7 +114,7 @@ func NodeFailedCondition(node, module, fp string, f NodeFailure, raised bool) oc
|
||||
// naming the module, the node and the rule holding its first want back with the rule's words, under the assigner's own name keyed by
|
||||
// node and module, and cleared (raised false) when the node has a want for it again.
|
||||
func NeitherCondition(node, module string, h Holding, raised bool) oc.Condition {
|
||||
key := delivery.AssignerModule + ".neither." + node + "." + module
|
||||
key := mmac.Module + ".neither." + node + "." + module
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: module, Machine: node}
|
||||
if !raised {
|
||||
return oc.Condition{Key: key, Subject: subject, State: occ.StateCleared,
|
||||
@@ -236,7 +236,7 @@ func BackupAsk(key, node, module, fp, digest, words string, asking int, now time
|
||||
// BackupCondition is the condition raised when a backup before an apply fails and the module is held on the node (ADR 0539 §16),
|
||||
// naming the node, the module and the backup's words; cleared under the same key.
|
||||
func BackupCondition(node, module, fp, words string, raised bool) oc.Condition {
|
||||
key := delivery.AssignerModule + ".backup." + node + "." + module + "." + strings.TrimPrefix(fp, meshcatalogclient.SourcePrefix2)
|
||||
key := mmac.Module + ".backup." + node + "." + module + "." + strings.TrimPrefix(fp, meshcatalogclient.SourcePrefix2)
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: module, Machine: node}
|
||||
if !raised {
|
||||
return oc.Condition{Key: key, Subject: subject, State: occ.StateCleared}
|
||||
|
||||
@@ -2,6 +2,7 @@ package assign
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
)
|
||||
|
||||
@@ -160,7 +160,7 @@ func saidConditionsAreFindings(t *testing.T) {
|
||||
t.Fatalf("%s: %v", c.key, err)
|
||||
}
|
||||
got, ok := puts[c.key]
|
||||
if !ok || got.Severity != health.Severity(c.raised.Severity) || got.Headline != c.raised.Headline || got.Observer != delivery.AssignerModule ||
|
||||
if !ok || got.Severity != health.Severity(c.raised.Severity) || got.Headline != c.raised.Headline || got.Observer != mmac.Module ||
|
||||
got.Subject.Machine != c.raised.Subject.Machine || said != 0 {
|
||||
t.Fatalf("%s: finding %+v (written %v), said %d", c.key, got, puts, said)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ package assign
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
)
|
||||
|
||||
@@ -20,13 +20,13 @@ import (
|
||||
// assigner no longer says it straight (never both).
|
||||
|
||||
// FindingsBucket is the assigner's findings.
|
||||
var FindingsBucket = health.FindingsBucket(delivery.AssignerModule)
|
||||
var FindingsBucket = health.FindingsBucket(mmac.Module)
|
||||
|
||||
// FindingOf is a said condition as a finding: its key `<scope>.<id>.<kind>`, from the condition's own key
|
||||
// `mesh-delivery-assigner.<kind>.<id…>` (the subject's id when the key names none), its words unchanged. raised is false for
|
||||
// a clear, whose key is to be deleted; value is nil then.
|
||||
func FindingOf(c oc.Condition, at time.Time) (key string, value []byte, raised bool, err error) {
|
||||
rest, ok := strings.CutPrefix(c.Key, delivery.AssignerModule+".")
|
||||
rest, ok := strings.CutPrefix(c.Key, mmac.Module+".")
|
||||
if !ok || rest == "" {
|
||||
return "", nil, false, fmt.Errorf("the condition %q is not the assigner's", c.Key)
|
||||
}
|
||||
@@ -56,7 +56,7 @@ func FindingOf(c oc.Condition, at time.Time) (key string, value []byte, raised b
|
||||
value, err = health.EncodeFinding(health.Finding{Key: key, Kind: kind, Subject: health.Subject{Scope: scope, ID: id, Machine: c.Subject.Machine},
|
||||
Severity: health.Severity(c.Severity), Summary: summary, Headline: c.Headline, Explanation: c.Explanation, Resolved: c.Resolved,
|
||||
Needs: c.Needs, Actions: actions, Evidence: []health.Evidence{{At: at.UTC(), Said: summary}}, Source: "assigner." + kind,
|
||||
Observer: delivery.AssignerModule, At: at.UTC()})
|
||||
Observer: mmac.Module, At: at.UTC()})
|
||||
return key, value, true, err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package assign
|
||||
|
||||
import (
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"strings"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
)
|
||||
|
||||
// SeatWaitsCondition is the assigner's word on the seat mesh-placement while a state of the seat is not bound (ADR 0567
|
||||
// §1): raised naming each, cleared when none is left.
|
||||
func SeatWaitsCondition(unbound []string) oc.Condition {
|
||||
key := delivery.AssignerModule + ".seat-states"
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: delivery.AssignerModule}
|
||||
key := mmac.Module + ".seat-states"
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: mmac.Module}
|
||||
if len(unbound) == 0 {
|
||||
return oc.Condition{Key: key, Subject: subject, State: occ.StateCleared, Resolved: "the seat mesh-placement holds all its states."}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package assign
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -10,7 +11,6 @@ import (
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
||||
)
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
// catalogue.Upgrade: a person's choice over the module's word, its irreplaceable data and the default, the bus as any module (ADR 0601 §1).
|
||||
|
||||
// PoliciesBucket is the assigner's state `policies`.
|
||||
var PoliciesBucket = delivery.AssignerModule + "_" + buckets.PoliciesState
|
||||
var PoliciesBucket = mmac.Module + "_" + buckets.PoliciesState
|
||||
|
||||
// DecodePolicies reads the policies state's values by key (the module); a value that cannot be read is left out, named.
|
||||
func DecodePolicies(values map[string][]byte) (map[string]catalogue.PersonPolicy, []string) {
|
||||
@@ -73,7 +73,7 @@ func ProvisionFailedFinding(key string, p provisions.Provision, at time.Time) ([
|
||||
Severity: health.Warning, Summary: summary, Headline: clipHeadline(p.Consumer.Module + " waits for a provision that failed"),
|
||||
Explanation: occ.NothingToDo + " " + summary + ". It clears once the provider provides it.",
|
||||
Resolved: p.Provision + " for " + p.Consumer.Module + " is provided", Evidence: []health.Evidence{{At: at.UTC(), Said: p.Why}},
|
||||
Source: "assigner." + KindProvisionFailed, Observer: delivery.AssignerModule, At: at.UTC()})
|
||||
Source: "assigner." + KindProvisionFailed, Observer: mmac.Module, At: at.UTC()})
|
||||
}
|
||||
|
||||
func also(provider, consumer string) []string {
|
||||
@@ -105,7 +105,7 @@ func ProvisionMissingFinding(key string, bound time.Duration, at time.Time) ([]b
|
||||
Severity: health.Warning, Summary: summary, Headline: clipHeadline(module + " on " + node + " lacks " + provision),
|
||||
Explanation: occ.NothingToDo + " " + summary + ". It clears once the provision has its key.",
|
||||
Resolved: provision + " for " + module + " on " + node + " has its key", Evidence: []health.Evidence{{At: at.UTC(), Said: summary}},
|
||||
Source: "assigner." + KindProvisionMissing, Observer: delivery.AssignerModule, At: at.UTC()})
|
||||
Source: "assigner." + KindProvisionMissing, Observer: mmac.Module, At: at.UTC()})
|
||||
}
|
||||
|
||||
// KindUnplaced is, from the lease write, a node that runs but no placement names (ADR 0571 §6).
|
||||
@@ -125,7 +125,7 @@ func UnplacedFinding(node string, at time.Time) ([]byte, error) {
|
||||
Headline: clipHeadline(node + " has no placement"), Needs: "place it with mesh-placement.propose.",
|
||||
Explanation: occ.NeedsYou + "place it with mesh-placement.propose. " + summary + ".",
|
||||
Resolved: node + " is placed", Evidence: []health.Evidence{{At: at.UTC(), Said: summary}},
|
||||
Source: "assigner." + KindUnplaced, Observer: delivery.AssignerModule, At: at.UTC()})
|
||||
Source: "assigner." + KindUnplaced, Observer: mmac.Module, At: at.UTC()})
|
||||
}
|
||||
|
||||
func clipHeadline(s string) string {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
plc "mesh-delivery-assigner/internal/placement"
|
||||
)
|
||||
@@ -178,7 +177,7 @@ const (
|
||||
// CallClearedCondition clears the condition of a refused controller call a previous process raised, for its pair (node and
|
||||
// module, or node and provision for a pin).
|
||||
func CallClearedCondition(kind, node, module string) oc.Condition {
|
||||
return oc.Condition{Key: delivery.AssignerModule + "." + kind + "." + node + "." + module,
|
||||
return oc.Condition{Key: mmac.Module + "." + kind + "." + node + "." + module,
|
||||
Subject: oc.ConditionSubject{Scope: "module", ID: module, Machine: node}, State: occ.StateCleared,
|
||||
Resolved: "the assigner calls no verb of the controller any more: placement is the one source."}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,11 @@ const (
|
||||
// Source and Merges are the gate's.
|
||||
Source = "mesh-delivery-gate_" + delivery.StateSource
|
||||
Merges = "mesh-delivery-gate_" + delivery.StateMerges
|
||||
// TellerModule is the module whose hand the operator's answers pass: the one that holds each ask's answer, and the
|
||||
// name the hand-act log records a warrant under. Held equal to the manifest's reads by its test.
|
||||
TellerModule = "mesh-delivery-teller"
|
||||
// Answers holds the teller's answer to each ask.
|
||||
Answers = "mesh-delivery-teller_answers"
|
||||
Answers = TellerModule + "_answers"
|
||||
// Builds is the builder's.
|
||||
Builds = builds.BuilderBuildsBucket
|
||||
// Grants is the grants part's.
|
||||
|
||||
@@ -13,7 +13,7 @@ func TestBucketsAreTheEarlierNames(t *testing.T) {
|
||||
"Builds": {Builds, "mesh-delivery-builder_builds"}, "Grants": {Grants, "mesh-grants_grants"},
|
||||
"Wants": {Wants, "mesh-delivery-assigner_wants"}, "Differences": {Differences, "mesh-delivery-assigner_differences"},
|
||||
"Asks": {Asks, "mesh-delivery-assigner_asks"}, "Puts": {Puts, "mesh-delivery-assigner_puts"},
|
||||
"Policies": {Policies, "mesh-delivery-assigner_policies"},
|
||||
"Policies": {Policies, "mesh-delivery-assigner_policies"}, "TellerModule": {TellerModule, "mesh-delivery-teller"},
|
||||
} {
|
||||
if c[0] != c[1] {
|
||||
t.Errorf("%s = %q, want %q", name, c[0], c[1])
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
|
||||
nec "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
plc "mesh-delivery-assigner/internal/placement"
|
||||
)
|
||||
@@ -169,11 +169,11 @@ func JudgeAnswers(p mma.Proposal, intended map[string]map[string]bool, answers m
|
||||
}
|
||||
switch {
|
||||
case len(v.Fails) > 0:
|
||||
v.State = delivery.VerdictFail
|
||||
v.State = mdcc.VerdictFail
|
||||
case len(waiting) > 0:
|
||||
v.State = plc.VerdictWaits
|
||||
default:
|
||||
v.State = delivery.VerdictPass
|
||||
v.State = mdcc.VerdictPass
|
||||
}
|
||||
return v
|
||||
}
|
||||
@@ -259,7 +259,7 @@ func differenceWords(d nodeengine.CandidateDiffers) string {
|
||||
// shownValue bounds a value named in a brief.
|
||||
const shownValue = 60
|
||||
|
||||
// walk follows a differing path (delivery.DifferingPaths: keys joined by dots, a key may hold dots, and a JSON value
|
||||
// walk follows a differing path (the node-engine's DifferingPaths: keys joined by dots, a key may hold dots, and a JSON value
|
||||
// written in a string is read as JSON) through a body, answering the keys it passed and the value at its end.
|
||||
func walk(body, path string) (keys []string, value any, ok bool) {
|
||||
var v any
|
||||
|
||||
@@ -2,13 +2,13 @@ package judge
|
||||
|
||||
import (
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
mdcc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliverycheckerclient"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
plc "mesh-delivery-assigner/internal/placement"
|
||||
)
|
||||
@@ -49,22 +49,22 @@ func TestJudge(t *testing.T) {
|
||||
words string
|
||||
marked string
|
||||
}{
|
||||
{"all the same", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
|
||||
{"all the same", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, mdcc.VerdictPass, "", ""},
|
||||
{"a module added where intended", false, map[string]*nodeengine.CandidateAnswer{"anchor": {Proposal: "p-one", Revision: 7, Verdict: nodeengine.CandidateAnswerVerdictDiffers,
|
||||
Added: []nodeengine.CandidateAdded{{Module: "web", Unissued: []string{"its own secret"}}}}, "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
|
||||
{"a difference not computed passes, marked", false, map[string]*nodeengine.CandidateAnswer{"anchor": differs(7, "mail"), "laptop": same(8)}, nil, delivery.VerdictPass, "", "mail"},
|
||||
Added: []nodeengine.CandidateAdded{{Module: "web", Unissued: []string{"its own secret"}}}}, "laptop": same(8)}, nil, mdcc.VerdictPass, "", ""},
|
||||
{"a difference not computed passes, marked", false, map[string]*nodeengine.CandidateAnswer{"anchor": differs(7, "mail"), "laptop": same(8)}, nil, mdcc.VerdictPass, "", "mail"},
|
||||
{"the seed carries a difference, named", true, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8,
|
||||
Verdict: nodeengine.CandidateAnswerVerdictDiffers, Differs: []nodeengine.CandidateDiffers{{Module: "node-tools", Resource: "node-tools.runtime", Why: "the resource differs",
|
||||
Bodies: []nodeengine.CandidateBodies{{ID: "node-tools.runtime", Paths: []string{"env.MESH_OWNED_PATHS./etc/resolv.conf", "env.MESH_TOOL_MODULES"},
|
||||
Running: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/hosts\":\"hostname\",\"/etc/resolv.conf\":\"networkmanager (node-uplink)\"}"}}`,
|
||||
Composed: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/hosts\":\"hostname\",\"/etc/resolv.conf\":\"systemd-resolved (node-resolver)\"}","MESH_TOOL_MODULES":"… (cut at 8192 bytes)`}}}}}}, nil, delivery.VerdictPass, "", ""},
|
||||
Composed: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/hosts\":\"hostname\",\"/etc/resolv.conf\":\"systemd-resolved (node-resolver)\"}","MESH_TOOL_MODULES":"… (cut at 8192 bytes)`}}}}}}, nil, mdcc.VerdictPass, "", ""},
|
||||
{"a refusal", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8, Verdict: nodeengine.CandidateAnswerVerdictRefused,
|
||||
Refusals: []nodeengine.CandidateRefusal{{Module: "web", Why: "no own secret"}}}}, nil, delivery.VerdictFail, "laptop refuses", ""},
|
||||
Refusals: []nodeengine.CandidateRefusal{{Module: "web", Why: "no own secret"}}}}, nil, mdcc.VerdictFail, "laptop refuses", ""},
|
||||
{"a node not answering, within its bound", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7)}, map[string]bool{"laptop": true}, plc.VerdictWaits, "laptop (offline)", ""},
|
||||
{"an answer of an earlier revision, past its bound, is no answer and decided without it", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(6), "laptop": same(8)}, nil, delivery.VerdictPass, "no answer from anchor", ""},
|
||||
{"an answer of an earlier revision, past its bound, is no answer and decided without it", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(6), "laptop": same(8)}, nil, mdcc.VerdictPass, "no answer from anchor", ""},
|
||||
{"a module held as today passes, shown in the brief", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": {Proposal: "p-one", Revision: 8,
|
||||
Verdict: nodeengine.CandidateAnswerVerdictSame, Held: []nodeengine.CandidateRefusal{{Module: "spiegel", Why: "a required value is unset"}}}}, nil, delivery.VerdictPass, "", ""},
|
||||
{"its later answer", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, delivery.VerdictPass, "", ""},
|
||||
Verdict: nodeengine.CandidateAnswerVerdictSame, Held: []nodeengine.CandidateRefusal{{Module: "spiegel", Why: "a required value is unset"}}}}, nil, mdcc.VerdictPass, "", ""},
|
||||
{"its later answer", false, map[string]*nodeengine.CandidateAnswer{"anchor": same(7), "laptop": same(8)}, nil, mdcc.VerdictPass, "", ""},
|
||||
} {
|
||||
q := p
|
||||
q.Seed = row.seed
|
||||
@@ -73,10 +73,10 @@ func TestJudge(t *testing.T) {
|
||||
if v.State != row.state || !strings.Contains(all, row.words) {
|
||||
t.Errorf("%s: %s, %q", row.name, v.State, all)
|
||||
}
|
||||
if row.seed && row.state == delivery.VerdictPass && !strings.Contains(Brief(q, v), "the seed carries: node-tools: MESH_OWNED_PATHS[/etc/resolv.conf] networkmanager (node-uplink) → (value cut) (and 1 more fields)") {
|
||||
if row.seed && row.state == mdcc.VerdictPass && !strings.Contains(Brief(q, v), "the seed carries: node-tools: MESH_OWNED_PATHS[/etc/resolv.conf] networkmanager (node-uplink) → (value cut) (and 1 more fields)") {
|
||||
t.Errorf("%s: the brief does not name it: %s", row.name, Brief(q, v))
|
||||
}
|
||||
if row.seed && row.state == delivery.VerdictPass {
|
||||
if row.seed && row.state == mdcc.VerdictPass {
|
||||
whole := row.answers["laptop"].Differs[0]
|
||||
whole.Bodies = []nodeengine.CandidateBodies{{ID: "r", Paths: []string{"env.MESH_OWNED_PATHS./etc/resolv.conf"},
|
||||
Running: `{"env":{"MESH_OWNED_PATHS":"{\"/etc/resolv.conf\":\"networkmanager (node-uplink)\"}"}}`,
|
||||
|
||||
Reference in New Issue
Block a user