No client names a holder: each reader keeps its own constant, held to its manifest (ADR 0625 section 4, issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -35,13 +35,6 @@ func TestDigestAndFingerprintSetKeepTheirForms(t *testing.T) {
|
||||
}
|
||||
|
||||
// A manifest and a module are read back as written, and each rule of the old values is kept: a refusal names its reason.
|
||||
// The holder's states others read keep the addresses the manifests' `reads` and the first views name today.
|
||||
func TestTheHoldersReadAddressesAreTheOnesTheManifestsName(t *testing.T) {
|
||||
if Module != "mesh-delivery-indexer" || ModulesRead != "mesh-delivery-indexer.modules" || ManifestsRead != "mesh-delivery-indexer.manifests" {
|
||||
t.Errorf("the holder %q reads %q and %q", Module, ModulesRead, ManifestsRead)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManifestAndModuleValuesKeepTheirRules(t *testing.T) {
|
||||
if _, err := ManifestsKey("abc"); err == nil || !strings.Contains(err.Error(), `"abc"`) {
|
||||
t.Errorf("ManifestsKey(abc) = %v", err)
|
||||
|
||||
@@ -10,15 +10,6 @@ import (
|
||||
"git.novox.be/novox/mesh-sdk/go/keys"
|
||||
)
|
||||
|
||||
// Module is the module that holds the seat mesh-catalog, and the two states of its others read, by the address a
|
||||
// manifest's `reads` and a first view name them: the modules the trunk holds and their manifests. A reader names them here,
|
||||
// never by the holder's literal name.
|
||||
const (
|
||||
Module = "mesh-delivery-indexer"
|
||||
ModulesRead = Module + ".modules"
|
||||
ManifestsRead = Module + ".manifests"
|
||||
)
|
||||
|
||||
// RootPath is a `modules` value's path when the module's manifest is its repository's root.
|
||||
const RootPath = "."
|
||||
|
||||
|
||||
@@ -7,6 +7,19 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
@@ -17,22 +30,13 @@ import (
|
||||
"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"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats-server/v2/server"
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
"mesh-delivery-assigner/internal/judge"
|
||||
|
||||
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"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
@@ -44,7 +48,6 @@ import (
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
||||
"mesh-delivery-assigner/internal/judge"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
@@ -122,7 +125,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." + meshcatalogclient.Module + ".event.views.>"}, AckPolicy: jetstream.AckExplicitPolicy}); err != nil {
|
||||
FilterSubjects: []string{enginereads.SubjectPrefix + "*", "mesh.mod." + buckets.IndexerModule + ".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.
|
||||
@@ -387,7 +390,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, meshcatalogclient.Module+"_") {
|
||||
if strings.HasPrefix(name, buckets.IndexerModule+"_") {
|
||||
t.Errorf("the assigner reads the indexer's state %s itself", name)
|
||||
}
|
||||
}
|
||||
@@ -427,10 +430,10 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) {
|
||||
"seat-holders": {"n1.node-tools"},
|
||||
"wants": {"n1.mesh-grants"},
|
||||
})
|
||||
graphKey := meshconditionsclient.Key(meshconditionsclient.ScopeModule, mmac.Module+"."+meshcatalogclient.Module+"."+graph.State, views.UnansweredKind)
|
||||
graphKey := meshconditionsclient.Key(meshconditionsclient.ScopeModule, placement.Module+"."+buckets.IndexerModule+"."+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()), meshcatalogclient.Module+".graph")
|
||||
return err == nil && strings.Contains(string(e.Value()), buckets.IndexerModule+".graph")
|
||||
}
|
||||
for deadline := time.Now().Add(10 * time.Second); !graphRaised(); time.Sleep(50 * time.Millisecond) {
|
||||
if time.Now().After(deadline) {
|
||||
@@ -1092,7 +1095,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[mmac.Module+"_"+state]
|
||||
return s.b.buckets[placement.Module+"_"+state]
|
||||
}
|
||||
|
||||
func (s bedStore) get(state, key string) ([]byte, uint64, bool, error) {
|
||||
@@ -1127,7 +1130,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_" + mmac.Module + "_placement",
|
||||
if _, err := b.js.CreateStream(b.ctx, jetstream.StreamConfig{Name: "MOD_" + placement.Module + "_placement",
|
||||
Subjects: placementSubjects()}); err != nil { // the seat's four events: the views family has a stream of its own
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1379,8 +1382,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: 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())
|
||||
f := &views.Follower{Owner: placement.Module, Tool: state, State: state, Ask: func(context.Context, string) (views.Answer, error) {
|
||||
return views.FirstView(placement.Module, state, src(kv), src(marks), "", time.Now())
|
||||
}}
|
||||
if err := f.Start(b.ctx); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -1389,7 +1392,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 != mmac.Module || views.StateOfEvent(m.Subject) != state {
|
||||
if owner, _ := views.OwnerOfEvent(m.Subject); err != nil || owner != placement.Module || views.StateOfEvent(m.Subject) != state {
|
||||
continue
|
||||
}
|
||||
e, err := views.DecodeEvent(m.Data)
|
||||
@@ -1447,7 +1450,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(mmac.Module, e))
|
||||
out = append(out, process.ModuleStreamSubject(placement.Module, e))
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -1461,11 +1464,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: meshcatalogclient.Module + "_" + views.MarksState, History: 1})
|
||||
marks, err := b.js.CreateKeyValue(b.ctx, jetstream.KeyValueConfig{Bucket: buckets.IndexerModule + "_" + views.MarksState, History: 1})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
em := views.Emitter{Owner: meshcatalogclient.Module, Subject: process.Account{Node: "n1", Module: meshcatalogclient.Module}.EventSubject,
|
||||
em := views.Emitter{Owner: buckets.IndexerModule, Subject: process.Account{Node: "n1", Module: buckets.IndexerModule}.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})
|
||||
@@ -1490,7 +1493,7 @@ func serveIndexer(t *testing.T, b *bed, nc *nats.Conn) {
|
||||
After string `json:"after"`
|
||||
}
|
||||
_ = json.Unmarshal(m.Data, &args)
|
||||
a, err := views.FirstView(meshcatalogclient.Module, state, bedSource{b.ctx, kv}, bedSource{b.ctx, marks}, args.After, time.Now())
|
||||
a, err := views.FirstView(buckets.IndexerModule, 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()}
|
||||
@@ -1550,7 +1553,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(mmac.Module, viewTools(func(k string) string { return env[k] }, state, time.Now), inR, outW)
|
||||
_ = stdio.ServeOn(placement.Module, viewTools(func(k string) string { return env[k] }, state, time.Now), inR, outW)
|
||||
}()
|
||||
answers := make(chan map[string]any, 16)
|
||||
go func() {
|
||||
@@ -1571,7 +1574,7 @@ func firstViewsBeforeAnyNewFormState(t *testing.T, b *bed, granted map[string][]
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(nc.Close)
|
||||
sub, err := nc.Subscribe("mesh.mod."+mmac.Module+".call.*.*", func(msg *nats.Msg) {
|
||||
sub, err := nc.Subscribe("mesh.mod."+placement.Module+".call.*.*", func(msg *nats.Msg) {
|
||||
one <- struct{}{}
|
||||
defer func() { <-one }()
|
||||
tokens := strings.Split(msg.Subject, ".")
|
||||
@@ -1603,7 +1606,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."+mmac.Module+".call."+tool+"."+strings.ReplaceAll(user, ".", "~"), data, 5*time.Second)
|
||||
msg, err := nc.Request("mesh.mod."+placement.Module+".call."+tool+"."+strings.ReplaceAll(user, ".", "~"), data, 5*time.Second)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1619,7 +1622,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 != mmac.Module || a.State != tool || len(a.Values) != len(keys) {
|
||||
if a.Owner != placement.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,10 +10,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"io"
|
||||
"log"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"os"
|
||||
"os/signal"
|
||||
"slices"
|
||||
@@ -85,7 +85,7 @@ var ownBuckets = []string{buckets.Asks, buckets.Differences,
|
||||
const engineReadsState = "engine-reads"
|
||||
|
||||
// engineReadsBucket is that state's bucket.
|
||||
const engineReadsBucket = mmac.Module + "_" + engineReadsState
|
||||
const engineReadsBucket = placement.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(mmac.Module)
|
||||
subject, err := occ.ConditionSubject(placement.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: mmac.Module}
|
||||
account := process.Account{Node: thisNode, Module: placement.Module}
|
||||
w := notHeardWriter(findings, logf)
|
||||
handle := func(m jetstream.Msg) {
|
||||
if err := m.Ack(); err != nil {
|
||||
|
||||
@@ -6,6 +6,13 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
wdc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
||||
mwc "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||
@@ -16,12 +23,6 @@ import (
|
||||
"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"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
|
||||
@@ -363,7 +364,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, meshcatalogclient.Module + ".modules": modules})
|
||||
s := newPutTools(memStore{putsState: putsKV, builds.BuilderModule + ".builds": buildKV, buckets.IndexerModule + ".modules": modules})
|
||||
s.now = func() time.Time { return now }
|
||||
was := answerWithin
|
||||
answerWithin = 0
|
||||
@@ -1130,7 +1131,7 @@ func aWantWaitsOnTheVerbEdgesTheGraphKeeps(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.w.put(graph.Bucket, module, raw)
|
||||
p.w.put(buckets.Graph, module, raw)
|
||||
}
|
||||
g := p.moduleGraph()
|
||||
if got := keptInvokes(g, "caller"); !slices.Equal(got, []string{"seat:x.v"}) || keptInvokes(g, "unknown") != nil {
|
||||
|
||||
@@ -5,19 +5,21 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"reflect"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/nats-io/nats.go/jetstream"
|
||||
@@ -56,7 +58,7 @@ func seatPublisher(ctx context.Context, js jetstream.JetStream, node string) pub
|
||||
}
|
||||
msg := nats.NewMsg(seatdef.EventSubject(mma.Seat, event))
|
||||
msg.Header.Set("x-event-id", id)
|
||||
msg.Header.Set("x-source", mmac.Module)
|
||||
msg.Header.Set("x-source", placement.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")
|
||||
|
||||
@@ -4,14 +4,16 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"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"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
|
||||
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"
|
||||
@@ -42,7 +44,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 = meshcatalogclient.Module + ".modules"
|
||||
modulesState = buckets.IndexerModule + ".modules"
|
||||
haveState = "node-engine.have"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"os"
|
||||
"regexp"
|
||||
@@ -15,6 +14,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||
@@ -76,7 +78,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(meshcatalogclient.ModulesRead, module)
|
||||
raw, _, found, err := s.st.get(buckets.ModulesRead, module)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("the indexer's modules cannot be read: %w", err)
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"slices"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||
@@ -23,7 +24,7 @@ import (
|
||||
// does not decode is left out, so its module waits on no verb.
|
||||
func (p *passer) moduleGraph() graph.Graph {
|
||||
g := graph.Graph{}
|
||||
for key, raw := range p.w.read(graph.Bucket) {
|
||||
for key, raw := range p.w.read(buckets.Graph) {
|
||||
module, err := graph.ParseKey(key)
|
||||
if err != nil {
|
||||
continue
|
||||
|
||||
@@ -3,9 +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"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
@@ -28,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
// marksBucket is the assigner's state of what its views family said each state up to.
|
||||
var marksBucket = mmac.Module + "_" + views.MarksState
|
||||
var marksBucket = placement.Module + "_" + views.MarksState
|
||||
|
||||
// viewedTool is one tool over one state of the assigner's.
|
||||
type viewedTool struct{ tool, state, words string }
|
||||
@@ -67,13 +66,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(mmac.Module, t.tool, t.state, t.words, views.ParseCallers(getenv(views.CallersEnv(t.tool))), state(t.state), marks, now))
|
||||
out = append(out, views.FirstViewTool(placement.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(mmac.Module, t.tool, t.state, t.words, state(t.state), marks, now))
|
||||
out = append(out, views.ReadTool(placement.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(mmac.Module, "assigner_first_views", "assigner_first_view_again", stdio.State(views.StatusState), meshhandactsclient.Recorder{Ask: stdio.Ask}, now)...)
|
||||
return append(out, views.StatusTools(placement.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)} }
|
||||
@@ -85,7 +84,7 @@ func startViews(ctx context.Context, js jetstream.JetStream, nc process.Subscrib
|
||||
if findings.Put == nil {
|
||||
return
|
||||
}
|
||||
if err := viewFindings(findings).Put(views.TooLargeFinding(mmac.Module, state, key, size, time.Now())); err != nil {
|
||||
if err := viewFindings(findings).Put(views.TooLargeFinding(placement.Module, state, key, size, time.Now())); err != nil {
|
||||
logf("views: the finding of %s.%s too large is not written: %v", state, key, err)
|
||||
}
|
||||
}
|
||||
@@ -110,7 +109,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: mmac.Module, Subject: account.EventSubject, Publish: views.JetStreamPublish(js), Marks: mk, TooLarge: tooLarge, Logf: logf}
|
||||
em := views.Emitter{Owner: placement.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)
|
||||
}
|
||||
@@ -123,7 +122,7 @@ func viewFindings(f assign.Findings) views.FindingWriter {
|
||||
}
|
||||
|
||||
// firstViewsBucket is the assigner's own state of its first views (views.StatusState).
|
||||
var firstViewsBucket = mmac.Module + "_" + views.StatusState
|
||||
var firstViewsBucket = placement.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;
|
||||
@@ -141,7 +140,7 @@ type indexerViews struct {
|
||||
// indexerFirstViews are the indexer's states the assigner takes by first view and the views family, each by the name of
|
||||
// the indexer's bucket the world keeps it under: manifests and modules (ADR 0621 §2), and the module graph, whose verb
|
||||
// edges a want waits on (ADR 0614 §2, §3; ADR 0631 §1).
|
||||
var indexerFirstViews = map[string]string{"manifests": buckets.Manifests, "modules": buckets.Modules, graph.State: graph.Bucket}
|
||||
var indexerFirstViews = map[string]string{"manifests": buckets.Manifests, "modules": buckets.Modules, graph.State: buckets.Graph}
|
||||
|
||||
// firstViewBound and firstViewWait are each first view's bound before its condition is raised, and its first wait
|
||||
// between two failed asks; zero is the views package's (views.Bound, two minutes, ADR 0615 §6; and a first wait of five
|
||||
@@ -155,7 +154,7 @@ func (iv *indexerViews) start(ctx context.Context, w *world, wake func(), settle
|
||||
if iv.findings.Put == nil {
|
||||
return
|
||||
}
|
||||
f := views.UnansweredFinding(mmac.Module, s, time.Now())
|
||||
f := views.UnansweredFinding(placement.Module, s, time.Now())
|
||||
var err error
|
||||
if raised {
|
||||
err = viewFindings(iv.findings).Put(f)
|
||||
@@ -170,8 +169,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 := meshcatalogclient.Module + "." + state
|
||||
f := &views.Follower{Owner: meshcatalogclient.Module, Tool: tool, State: state, Ask: views.AskVia(iv.call, tool), Logf: iv.logf,
|
||||
tool := buckets.IndexerModule + "." + state
|
||||
f := &views.Follower{Owner: buckets.IndexerModule, 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) {
|
||||
@@ -202,7 +201,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."+meshcatalogclient.Module+".event."+views.EventPrefix+"*", views.Hear(ctx, followers, iv.logf))
|
||||
return iv.hub.Handle("mesh.mod."+buckets.IndexerModule+".event."+views.EventPrefix+"*", views.Hear(ctx, followers, iv.logf))
|
||||
})
|
||||
return len(all)
|
||||
}
|
||||
@@ -210,7 +209,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: mmac.Module, Logf: logf, Put: findings.Put}
|
||||
w := heard.Writer{Observer: placement.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) {
|
||||
|
||||
@@ -4,17 +4,18 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshhandacts "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts"
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/seats/meshwants"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
meshhandacts "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts"
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/seats/meshwants"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
|
||||
mcc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
@@ -32,7 +33,7 @@ import (
|
||||
// The states the verbs read, as the runtime names them.
|
||||
const (
|
||||
policiesState = buckets.PoliciesState
|
||||
manifestsState = meshcatalogclient.Module + ".manifests"
|
||||
manifestsState = buckets.IndexerModule + ".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.
|
||||
|
||||
@@ -2,14 +2,15 @@ package assign
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
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"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"regexp"
|
||||
"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"
|
||||
@@ -68,7 +69,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 := mmac.Module + ".held." + module + "." + strings.TrimPrefix(fp, meshcatalogclient.SourcePrefix2)
|
||||
key := placement.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 +92,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 := mmac.Module + ".failed-alone." + node + "." + module
|
||||
key := placement.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 +115,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 := mmac.Module + ".neither." + node + "." + module
|
||||
key := placement.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 +237,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 := mmac.Module + ".backup." + node + "." + module + "." + strings.TrimPrefix(fp, meshcatalogclient.SourcePrefix2)
|
||||
key := placement.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,18 +2,19 @@ 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"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"mesh-delivery-assigner/internal/puts"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
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"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate"
|
||||
|
||||
mcc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient"
|
||||
mcseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
@@ -161,7 +162,7 @@ func saidConditionsAreFindings(t *testing.T) {
|
||||
t.Fatalf("%s: %v", c.key, err)
|
||||
}
|
||||
got, ok := puts[c.key]
|
||||
if !ok || got.Severity != c.raised.Severity || got.Headline != c.raised.Headline || got.Observer != mmac.Module ||
|
||||
if !ok || got.Severity != c.raised.Severity || got.Headline != c.raised.Headline || got.Observer != placement.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,7 +3,7 @@ package assign
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -21,13 +21,13 @@ import (
|
||||
// assigner no longer says it straight (never both).
|
||||
|
||||
// FindingsBucket is the assigner's findings.
|
||||
var FindingsBucket = mcc.FindingsBucket(mmac.Module)
|
||||
var FindingsBucket = mcc.FindingsBucket(placement.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, mmac.Module+".")
|
||||
rest, ok := strings.CutPrefix(c.Key, placement.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
|
||||
}
|
||||
f := mcc.Observation{Scope: scope, ID: id, Kind: kind, Machine: c.Subject.Machine, Severity: string(c.Severity), Summary: summary,
|
||||
Headline: c.Headline, Explanation: c.Explanation, Resolved: c.Resolved, Needs: c.Needs, Actions: actions,
|
||||
Source: "assigner." + kind}.Finding(mmac.Module, "", at)
|
||||
Source: "assigner." + kind}.Finding(placement.Module, "", at)
|
||||
value, err = mcc.EncodeFinding(f)
|
||||
return key, value, true, err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package assign
|
||||
|
||||
import (
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"strings"
|
||||
|
||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
// 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 := mmac.Module + ".seat-states"
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: mmac.Module}
|
||||
key := placement.Module + ".seat-states"
|
||||
subject := oc.ConditionSubject{Scope: "module", ID: placement.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,8 +3,8 @@ package assign
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"mesh-delivery-assigner/internal/buckets"
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -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 = mmac.Module + "_" + buckets.PoliciesState
|
||||
var PoliciesBucket = placement.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) {
|
||||
@@ -76,7 +76,7 @@ func ProvisionFailedFinding(key string, p meshprovisionerclient.Provision, at ti
|
||||
|
||||
// encode is the observation as the assigner's finding at at, in the seat's layout.
|
||||
func encode(o mcc.Observation, at time.Time) ([]byte, error) {
|
||||
return mcc.EncodeFinding(o.Finding(mmac.Module, "", at))
|
||||
return mcc.EncodeFinding(o.Finding(placement.Module, "", at))
|
||||
}
|
||||
|
||||
func also(provider, consumer string) []string {
|
||||
|
||||
@@ -2,18 +2,20 @@ package assign
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-assigner/asks"
|
||||
|
||||
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"
|
||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
|
||||
"mesh-delivery-assigner/internal/placement"
|
||||
plc "mesh-delivery-assigner/internal/placement"
|
||||
)
|
||||
|
||||
@@ -177,7 +179,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: mmac.Module + "." + kind + "." + node + "." + module,
|
||||
return oc.Condition{Key: placement.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."}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,16 @@ const (
|
||||
Have = "node-engine_" + nodeengine.StateHave
|
||||
// ComposedRead is the family of the node-engine's composed states, one bucket per node.
|
||||
ComposedRead = "mesh-host." + nodeengine.StateComposed
|
||||
// Modules and Manifests are the indexer's.
|
||||
Modules = "mesh-delivery-indexer_" + catalog.StateModules
|
||||
Manifests = "mesh-delivery-indexer_" + catalog.StateManifests
|
||||
// IndexerModule is the holder of the seat mesh-catalog, named from this module's manifest (`consumes` its views, `invokes`
|
||||
// its tools; TestTheIndexerIsTheManifests), since no client names a holder (ADR 0625 §4).
|
||||
IndexerModule = "mesh-delivery-indexer"
|
||||
// Modules, Manifests and Graph are the indexer's buckets; ModulesRead and ManifestsRead the addresses of the states
|
||||
// modules and manifests as a first view names them.
|
||||
Modules = IndexerModule + "_" + catalog.StateModules
|
||||
Manifests = IndexerModule + "_" + catalog.StateManifests
|
||||
Graph = IndexerModule + "_graph"
|
||||
ModulesRead = IndexerModule + "." + catalog.StateModules
|
||||
ManifestsRead = IndexerModule + "." + catalog.StateManifests
|
||||
// Presence holds each part's presence and the node's.
|
||||
Presence = "mesh-delivery-watchman_" + watchdogs.StatePresence
|
||||
// Source and Merges are the gate's.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
|
||||
)
|
||||
@@ -16,7 +15,7 @@ const (
|
||||
forgeBridgeModule = "mesh-delivery-forge-bridge"
|
||||
|
||||
// indexerModule is the holder of the states modules, manifests, candidates and packages the builder follows.
|
||||
indexerModule = meshcatalogclient.Module
|
||||
indexerModule = "mesh-delivery-indexer"
|
||||
// assignerModule is the holder of the state placement.
|
||||
assignerModule = buildrun.AssignerModule
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package check
|
||||
import (
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdelivery"
|
||||
checker "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdeliverychecker"
|
||||
@@ -28,7 +27,7 @@ const (
|
||||
|
||||
// IndexerModule holds the seat mesh-catalog's states, which the checker follows by their views (consumes:
|
||||
// mesh-delivery-indexer.views.*).
|
||||
IndexerModule = meshcatalogclient.Module
|
||||
IndexerModule = "mesh-delivery-indexer"
|
||||
CandidatesBucket = IndexerModule + "_" + meshcatalog.StateCandidates
|
||||
ModulesBucket = IndexerModule + "_" + meshcatalog.StateModules
|
||||
ManifestsBucket = IndexerModule + "_" + meshcatalog.StateManifests
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestIndexerWhole(t *testing.T) { // 1238/AC2, AC10; 1585/T14, T15
|
||||
}, func(ctx context.Context, js jetstream.JetStream) {
|
||||
// The states and the stream the controller makes from the indexer's manifest (old sections, ADR 0595 §11).
|
||||
for bucket, history := range map[string]uint8{index.PendingBucket: 1, index.VerdictsBucket: index.VerdictsHistory,
|
||||
graph.Bucket: 1, index.TakenBucket: 1, index.PackagesBucket: 1,
|
||||
index.GraphBucket: 1, index.TakenBucket: 1, index.PackagesBucket: 1,
|
||||
index.SeatDefinitionsBucket: 1, index.RequirementsBucket: 1, findingsBucket: 1, index.HoldsBucket: 1} {
|
||||
if _, err := js.CreateKeyValue(ctx, jetstream.KeyValueConfig{Bucket: bucket, History: history}); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -284,7 +284,7 @@ func TestIndexerWhole(t *testing.T) { // 1238/AC2, AC10; 1585/T14, T15
|
||||
if _, ok := get(index.VerdictsBucket, own.Manifest); !ok {
|
||||
t.Errorf("the verdict on the indexer's manifest %s is not written", own.Manifest)
|
||||
}
|
||||
if gk, _ := graph.Key(ix); !func() bool { _, ok := get(graph.Bucket, gk); return ok }() {
|
||||
if gk, _ := graph.Key(ix); !func() bool { _, ok := get(index.GraphBucket, gk); return ok }() {
|
||||
t.Errorf("the indexer's key %s of the module graph is not written", gk)
|
||||
}
|
||||
repoKey, _ := trunk.RepositoryKey(m1.Repository)
|
||||
|
||||
@@ -31,7 +31,6 @@ import (
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
|
||||
"mesh-delivery-indexer/internal/index"
|
||||
@@ -402,7 +401,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
// appears; until then indexer_requirements answers none, and the builder's floor waits on its answer.
|
||||
requirements := process.AwaitBucket(ctx, js, conn, index.RequirementsBucket, "what consumers require is not kept", logger.Printf)
|
||||
// The module graph (ADR 0603 §2): a state this delivery brings, bound when it appears; until then no graph is written.
|
||||
graph := process.AwaitBucket(ctx, js, conn, graph.Bucket, "no module graph is written", logger.Printf)
|
||||
graph := process.AwaitBucket(ctx, js, conn, index.GraphBucket, "no module graph is written", logger.Printf)
|
||||
findings := process.AwaitBucket(ctx, js, conn, findingsBucket, "no finding of the indexer is written", logger.Printf)
|
||||
// The seat definitions (design 26, DLV-I17): a state this delivery brings, bound when it appears; until then none is kept.
|
||||
seatDefs := process.AwaitBucket(ctx, js, conn, index.SeatDefinitionsBucket, "no seat definition is kept", logger.Printf)
|
||||
|
||||
@@ -92,7 +92,7 @@ type Indexer struct {
|
||||
ReadFile func(ctx context.Context, repository, sha, path string) ([]byte, error)
|
||||
// SaySeatDefinition says seat-definition-changed (seatdefs.go); nil says nothing.
|
||||
SaySeatDefinition func(ctx context.Context, c SeatDefinitionChanged) error
|
||||
// Graph is the module graph's state (graph.Bucket, graph.go; novox/hq ADR 0603 §2); nil writes no graph.
|
||||
// Graph is the module graph's state (GraphBucket, graph.go; novox/hq ADR 0603 §2); nil writes no graph.
|
||||
Graph Store
|
||||
// Files asks the forge for every blob under each directory at a commit, by directory then path relative to it, each
|
||||
// with its git object id (gitea.gitea_commit_trees with files): the listing a package's digest is computed from.
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// The module graph (novox/hq ADR 0603 §2): at every recompute the indexer writes, in its state graph
|
||||
// (graph.Bucket), one key per module it holds the inputs of, its build, provision and verb edges as that recompute
|
||||
// (GraphBucket), one key per module it holds the inputs of, its build, provision and verb edges as that recompute
|
||||
// computed them (ADR 0614 §1), the verb edges on a cycle left out over the whole graph (§3), and deletes the key of a module the modules state no longer holds. A key is written only when its value
|
||||
// changes, so its history of 5 is five changes of the module's edges. The delivery view, the checker and the seat
|
||||
// mesh-catalog's verbs read it; nothing stores an order (ADR 0603 §1).
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package index
|
||||
|
||||
import "git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||
|
||||
// The holders, states and buckets the indexer names, taken from its own manifest (module.json: its name, its `state`, its
|
||||
// `reads`) and from the manifests of the holders it reads; a unit row checks them against the manifest
|
||||
// (TestTheNamesAreTheManifests). No contract names a holder (novox/hq ADR 0625 §4, ADR 0634 §1).
|
||||
const (
|
||||
// Module is the indexer's own name; the catalog client's Module is the readers' name for it.
|
||||
// Module is the indexer's own name; each reader names it from its own manifest.
|
||||
Module = "mesh-delivery-indexer"
|
||||
|
||||
// The indexer's own states, with the revisions each keeps per key (module.json `state`).
|
||||
@@ -17,6 +19,8 @@ const (
|
||||
ManifestsState = "manifests"
|
||||
ManifestsBucket = Module + "_" + ManifestsState
|
||||
ManifestsHistory = 1
|
||||
// GraphBucket is the bucket of the state graph (sdk/graph names the state, not its holder).
|
||||
GraphBucket = Module + "_" + graph.State
|
||||
// VerdictsState and VerdictsBucket are in verdicts.go.
|
||||
VerdictsHistory = 5
|
||||
PredefinedState = "predefined"
|
||||
|
||||
@@ -48,7 +48,7 @@ var ViewedStates = map[string]string{
|
||||
ConfigCandidatesState: ConfigCandidatesBucket,
|
||||
"candidates": CandidatesBucket,
|
||||
PackagesState: PackagesBucket,
|
||||
graph.State: graph.Bucket,
|
||||
graph.State: GraphBucket,
|
||||
HeardState: HeardBucket,
|
||||
"taken": TakenBucket,
|
||||
mcc.FindingsState: mcc.FindingsBucket(Module),
|
||||
|
||||
@@ -125,7 +125,7 @@ func TestManifestDeclarations(t *testing.T) { // 1238/AC1, 1444 (reads the build
|
||||
t.Errorf("the indexer names itself %q, its manifest's module is %q", index.Module, m.Module)
|
||||
}
|
||||
for bucket, history := range map[string]int{index.CandidatesBucket: index.CandidatesHistory, index.ModulesBucket: index.ModulesHistory, index.ManifestsBucket: index.ManifestsHistory,
|
||||
index.VerdictsBucket: index.VerdictsHistory, index.PackagesBucket: index.PackagesHistory, index.TakenBucket: 1, index.PredefinedBucket: 5, index.ConfigCandidatesBucket: 5} {
|
||||
index.VerdictsBucket: index.VerdictsHistory, index.PackagesBucket: index.PackagesHistory, index.TakenBucket: 1, index.PredefinedBucket: 5, index.ConfigCandidatesBucket: 5, index.GraphBucket: graph.History} {
|
||||
if !slices.ContainsFunc(m.State, func(st state) bool { return m.Module+"_"+st.Name == bucket && st.History == history }) {
|
||||
t.Errorf("the indexer names its bucket %s with %d revisions, its manifest's states are %+v", bucket, history, m.State)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package view
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/trunk"
|
||||
"git.novox.be/novox/mesh-sdk/go/keys"
|
||||
@@ -13,7 +12,7 @@ import (
|
||||
// `consumes`); a unit row checks them against it (TestTheNamesAreTheManifests). No contract names a holder (novox/hq
|
||||
// ADR 0625 §4, ADR 0634 §1). The indexer's module and its reads are the catalog client's.
|
||||
const (
|
||||
IndexerModule = meshcatalogclient.Module
|
||||
IndexerModule = "mesh-delivery-indexer"
|
||||
AssignerModule = "mesh-delivery-assigner"
|
||||
WatchmanModule = "mesh-delivery-watchman"
|
||||
GateModule = "mesh-delivery-gate"
|
||||
|
||||
@@ -68,7 +68,7 @@ accounts {
|
||||
func serveOwners(t *testing.T, ctx context.Context, js jetstream.JetStream, nc *nats.Conn) {
|
||||
t.Helper()
|
||||
viewstest.Serve(t, ctx, js, nc, watch.AssignerModule, wantsState, watch.AssignerModule+".assigner_read_wants", "n1_"+watch.WatchmanModule)
|
||||
viewstest.Serve(t, ctx, js, nc, meshcatalogclient.Module, modulesState, meshcatalogclient.Module+".indexer_read_modules", "n1_"+watch.WatchmanModule)
|
||||
viewstest.Serve(t, ctx, js, nc, watch.IndexerModule, modulesState, watch.IndexerModule+".indexer_read_modules", "n1_"+watch.WatchmanModule)
|
||||
}
|
||||
|
||||
// TestWatchmanWhole starts the program the way the node does (its entry, run, with its environment and a broker file)
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
sdkfindings "git.novox.be/novox/mesh-delivery/sdk/findings"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
@@ -19,6 +18,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
sdkfindings "git.novox.be/novox/mesh-delivery/sdk/findings"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
"git.novox.be/novox/mesh-sdk/go/views"
|
||||
|
||||
@@ -27,7 +28,6 @@ import (
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
||||
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
|
||||
@@ -247,7 +247,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
modules, err := reader.Follow(meshcatalogclient.Module, modulesState, meshcatalogclient.Module+".indexer_read_modules")
|
||||
modules, err := reader.Follow(watch.IndexerModule, modulesState, watch.IndexerModule+".indexer_read_modules")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -455,7 +455,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
w.TakeInCaughtUp()
|
||||
}
|
||||
}
|
||||
if err := hub.Handle("mesh.mod."+meshcatalogclient.Module+".event.take-in.*", func(m jetstream.Msg) { takeInHeard(w, m, logger.Printf) }); err != nil {
|
||||
if err := hub.Handle("mesh.mod."+watch.IndexerModule+".event.take-in.*", func(m jetstream.Msg) { takeInHeard(w, m, logger.Printf) }); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -535,7 +535,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
||||
const eventsStream = "EVENTS"
|
||||
|
||||
// pendingTool is the indexer's tool that answers the waits it holds (ADR 0633 §5), as the view asks it.
|
||||
const pendingTool = meshcatalogclient.Module + ".indexer_pending"
|
||||
const pendingTool = watch.IndexerModule + ".indexer_pending"
|
||||
|
||||
// seedTakeIn asks the indexer the waits it holds now and starts each (Watchman.SeedTakeIn). An indexer that does not
|
||||
// answer is said: the waits are then known only from the events heard after.
|
||||
|
||||
@@ -2,7 +2,6 @@ package watch
|
||||
|
||||
import (
|
||||
meshwatchdogs "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs"
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
)
|
||||
|
||||
// The holders and buckets the watchman names, taken from its own manifest (module.json: its name, its `reads`, its
|
||||
@@ -11,7 +10,9 @@ import (
|
||||
const (
|
||||
WatchmanModule = "mesh-delivery-watchman"
|
||||
AssignerModule = "mesh-delivery-assigner"
|
||||
builderModule = "mesh-delivery-builder"
|
||||
// IndexerModule is the holder of the seat mesh-catalog, named from this module's manifest (consumes and invokes of mesh-delivery-indexer).
|
||||
IndexerModule = "mesh-delivery-indexer"
|
||||
builderModule = "mesh-delivery-builder"
|
||||
|
||||
// The watchman's own states of the seat mesh-watchdogs.
|
||||
PresenceBucket = WatchmanModule + "_" + meshwatchdogs.StatePresence
|
||||
@@ -26,7 +27,7 @@ const (
|
||||
// AssignerWantsBucket is the assigner's state wants, followed by its views family (consumes: mesh-delivery-assigner.views.wants).
|
||||
AssignerWantsBucket = AssignerModule + "_wants"
|
||||
// ModulesBucket is the indexer's state modules, followed by its views family (consumes: mesh-delivery-indexer.views.modules).
|
||||
ModulesBucket = meshcatalogclient.Module + "_modules"
|
||||
ModulesBucket = IndexerModule + "_modules"
|
||||
)
|
||||
|
||||
// The findings a value of another part is raised as, named by their words.
|
||||
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||
|
||||
"mesh-delivery-watchman/internal/watch"
|
||||
)
|
||||
|
||||
@@ -162,7 +160,7 @@ func TestManifestStateAndReads(t *testing.T) { // 1135/AC6
|
||||
"wants": {watch.AssignerWantsBucket, bucket(m.Consumes, "mesh-delivery-assigner.views.wants")},
|
||||
"modules": {watch.ModulesBucket, bucket(m.Consumes, "mesh-delivery-indexer.views.modules")},
|
||||
"assigner": {watch.AssignerModule + ".assigner_read_wants", entry(m.Invokes, "mesh-delivery-assigner.assigner_read_wants")},
|
||||
"indexer": {meshcatalogclient.Module + ".indexer_pending", entry(m.Invokes, "mesh-delivery-indexer.indexer_pending")},
|
||||
"indexer": {watch.IndexerModule + ".indexer_pending", entry(m.Invokes, "mesh-delivery-indexer.indexer_pending")},
|
||||
} {
|
||||
if row.got != row.want {
|
||||
t.Errorf("the name for %s is %q, its manifest's is %q", name, row.got, row.want)
|
||||
|
||||
@@ -2,9 +2,6 @@ package buscompose
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/meshbroker"
|
||||
"git.novox.be/novox/mesh-contracts/identity-and-access/go/seats/meshnodeenroller"
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -14,9 +11,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/meshbroker"
|
||||
"git.novox.be/novox/mesh-contracts/identity-and-access/go/seats/meshnodeenroller"
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/identity-and-access/go/clients/meshvaultclient"
|
||||
"git.novox.be/novox/mesh-contracts/identity-and-access/go/seats/meshvault"
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
@@ -60,7 +60,7 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
||||
// ADR 0567 §3, §9: a node reads every key of the seat's placement and its candidates (it composes with the whole
|
||||
// proposal laid over), and none of its open proposals; it writes neither.
|
||||
reads := strings.Join(NodeComposeReads("laptop"), " ")
|
||||
for bucket, granted := range map[string]bool{meshmoduleassignerclient.PlacementBucket: true, PlacementCandidatesBucket: true,
|
||||
for bucket, granted := range map[string]bool{PlacementBucket: true, PlacementCandidatesBucket: true,
|
||||
PlacementProposalsBucket: false} {
|
||||
if strings.Contains(reads, "$JS.API.DIRECT.GET.KV_"+bucket+".>") != granted || strings.Contains(reads, "$KV."+bucket+".laptop") {
|
||||
t.Errorf("a node is granted %s: %v, want %v", bucket, !granted, granted)
|
||||
@@ -655,7 +655,7 @@ func healthChecks(t *testing.T) {
|
||||
{Module: "mesh-provisioner-client", ProvisionsNode: true},
|
||||
// ADR 0571 clauses 2, 4 (issue 1955): the seat mesh-artifact-sweep says artifacts-gone; the assigner keeps seat-holders.
|
||||
{Module: "artifact-store-tools", Holds: []Seat{{Name: "mesh-artifact-sweep", Emits: []string{"artifacts-gone"}}},
|
||||
Reads: []string{meshmoduleassignerclient.SeatHoldersRead}},
|
||||
Reads: []string{SeatHoldersRead}},
|
||||
{Module: AssignerModule, State: []Bucket{bucket(AssignerModule, meshmoduleassigner.StateSeatHolders)}},
|
||||
// ADR 0571 clause 3: disk-load keeps the readings; the backup holder reads them.
|
||||
// ADR 0577 clause 1: and it reads its own node's keys of the node-engine's data items, which restic may not.
|
||||
|
||||
@@ -15,6 +15,13 @@ const (
|
||||
// EnrolmentModule is the module holding the seat mesh-node-enroller.
|
||||
EnrolmentModule = "mesh-enrolment"
|
||||
|
||||
// PlacementBucket and SeatHoldersBucket are the assigner's states placement and seat-holders (reads:
|
||||
// mesh-delivery-assigner.placement; the seat-holders state is read as a named reader), PlacementRead the address of the first.
|
||||
PlacementBucket = AssignerModule + "_placement"
|
||||
PlacementRead = AssignerModule + ".placement"
|
||||
SeatHoldersRead = AssignerModule + ".seat-holders"
|
||||
SeatHoldersBucket = AssignerModule + "_seat-holders"
|
||||
|
||||
AssignerWantsBucket = AssignerModule + "_wants"
|
||||
PlacementCandidatesBucket = AssignerModule + "_candidates"
|
||||
PlacementProposalsBucket = AssignerModule + "_placement-proposals"
|
||||
|
||||
@@ -32,6 +32,7 @@ func namesAreTheManifests(t *testing.T) {
|
||||
{"reads", HaveBucket[:strings.Index(HaveBucket, "_")] + ".have", HaveBucket},
|
||||
{"reads", NodeLoginsRead, NodeLoginsBucket},
|
||||
{"reads", EnrolmentsRead, EnrolmentsBucket},
|
||||
{"invokes", PlacementRead, PlacementBucket},
|
||||
{"invokes", AssignerModule + ".wants", AssignerWantsBucket},
|
||||
{"invokes", IndexerModule + ".modules", ModulesBucket},
|
||||
{"invokes", IndexerModule + ".manifests", ManifestsBucket},
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
@@ -49,7 +48,7 @@ var ProvisionerReads = []string{ConfigResolvedBucket}
|
||||
// reason** (2026-10-30 recovery, issue 774): the client V3 watches every machine's plans to bind a provider's
|
||||
// consumers, and granted only its own machine's keys it read none. ADR 0570 clause 3 has providers act on the seat's
|
||||
// provision keys instead; once the client does, plans go back to its own machine's keys.
|
||||
var ProvisionerReadsWhole = []string{meshmoduleassignerclient.PlacementBucket, meshprovisionerclient.PlansBucket}
|
||||
var ProvisionerReadsWhole = []string{PlacementBucket, meshprovisionerclient.PlansBucket}
|
||||
|
||||
// BoundState is a providing module's state of entries, one per consumer (mesh-sdk go/provider, issue 678): a
|
||||
// consumer's machine's client reads its own keys of it, `<node>.<module>.<provision>[.<local>]`, to fill
|
||||
|
||||
@@ -2,12 +2,12 @@ package buscompose
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
)
|
||||
|
||||
// A module's state on the bus (novox/hq ADR 0201, design 32 §4, design 25 §3).
|
||||
@@ -341,7 +341,7 @@ const ResolvedBucket = "mesh-config_resolved"
|
||||
// secret. Reads only; the node is checked as every subject token is by the caller's principal.
|
||||
func NodeComposeReads(node string) []string {
|
||||
var out []string
|
||||
for _, bucket := range []string{meshmoduleassignerclient.PlacementBucket, PlacementCandidatesBucket, ModulesBucket,
|
||||
for _, bucket := range []string{PlacementBucket, PlacementCandidatesBucket, ModulesBucket,
|
||||
ManifestsBucket, builds.BuilderBuildsBucket} {
|
||||
out = append(out, readGrants(bucket, "")...)
|
||||
}
|
||||
@@ -351,7 +351,7 @@ func NodeComposeReads(node string) []string {
|
||||
// NodeComposeAdvisories are the stream-created advisories of the seat mesh-placement's placement and candidates
|
||||
// (ADR 0567 §9): what a node agent hears to bind each once it is made. Those two and no wider.
|
||||
func NodeComposeAdvisories() []string {
|
||||
return []string{StreamCreatedAdvisory(meshmoduleassignerclient.PlacementBucket), StreamCreatedAdvisory(PlacementCandidatesBucket)}
|
||||
return []string{StreamCreatedAdvisory(PlacementBucket), StreamCreatedAdvisory(PlacementCandidatesBucket)}
|
||||
}
|
||||
|
||||
// ServedReadGrants is the read of each key of mesh-config's resolved values named, `<node>.<module>.<key>`
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"mesh-grants/internal/buscompose"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||
"git.novox.be/novox/mesh-contracts/identity-and-access/go/clients/meshvaultclient"
|
||||
@@ -30,7 +32,6 @@ import (
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-networking/modules/mesh-wireguard/go/overlay"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
"mesh-grants/internal/buscompose"
|
||||
)
|
||||
|
||||
// The states of other parts the grants part reads, as its manifest's reads name them (`<module>.<state>`).
|
||||
@@ -48,7 +49,7 @@ const (
|
||||
ReadAccounts = "mesh-vault.bus-accounts"
|
||||
// ReadPlacement is the seat mesh-placement's placement (ADR 0567 §1, §9): each node's modules and the seats
|
||||
// they hold.
|
||||
ReadPlacement = meshmoduleassignerclient.PlacementRead
|
||||
ReadPlacement = buscompose.PlacementRead
|
||||
// ReadEnrolments is the seat mesh-enrolment's open enrolments, read as a named reader (ADR 0587 §2, §4): a key at
|
||||
// live or redeeming composes the user enrol.<node>.
|
||||
ReadEnrolments = buscompose.EnrolmentsRead
|
||||
|
||||
+4
-6
@@ -65,12 +65,10 @@ func checkRepository(repository string) error {
|
||||
// operator, 2026-11-03: no graph-related code in mesh-sdk, only contracts). It names no module.
|
||||
|
||||
const (
|
||||
// State is the name of the indexer's state of the module graph, as its manifest declares it, and Bucket its
|
||||
// bucket: one key per module (Key).
|
||||
State = "graph"
|
||||
Bucket = meshcatalogclient.Module + "_" + State
|
||||
// Read is the line a reader's manifest names in `reads` to read the graph.
|
||||
Read = meshcatalogclient.Module + "." + State
|
||||
// State is the name of the indexer's state of the module graph, as its manifest declares it: one key per module
|
||||
// (Key). Its bucket is the holder's name and the state's, which the indexer and each reader name from its own
|
||||
// manifest, never this package (ADR 0625 §4).
|
||||
State = "graph"
|
||||
// History is the revisions the graph state keeps per key (ADR 0603 §2).
|
||||
History = 5
|
||||
)
|
||||
|
||||
@@ -213,7 +213,7 @@ func sampleNode() Node {
|
||||
// nodeValues: a node round-trips with its lists sorted, an unknown version is refused, a node that does not hold is
|
||||
// refused naming why, and the state is the indexer's graph (ADR 0603 §2).
|
||||
func nodeValues(t *testing.T) {
|
||||
if Bucket != "mesh-delivery-indexer_graph" || Read != "mesh-delivery-indexer.graph" || History != 5 || State != "graph" {
|
||||
if History != 5 || State != "graph" {
|
||||
t.Error("the graph's state differs from the decided layout")
|
||||
}
|
||||
g := sampleNode()
|
||||
|
||||
Reference in New Issue
Block a user