View read.go: the reads' names from the clients and the view's own constants (kept apart from the unit commit for the buildlog change of read.go)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 16:28:52 +01:00
parent 3456f34fa8
commit c85b150782
@@ -14,10 +14,17 @@ import (
"sync/atomic"
"time"
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
"git.novox.be/novox/mesh-contracts/identity-and-access/go/clients/meshvaultclient"
"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/seats/meshcatalog"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate"
"git.novox.be/novox/mesh-delivery/sdk/buildlog"
"git.novox.be/novox/mesh-delivery/sdk/trunk"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
// The read tools, named as the module is: indexer_ and the verb.
@@ -58,14 +65,14 @@ type Reader struct {
ConditionsState, AttemptsState, PresenceState, StuckState StateRead
// PredefinedState and ConfigCandidatesState are the indexer's control records (ADR 0565 §2, §15); unset reads none.
PredefinedState, ConfigCandidatesState StateRead
// PackagesState is the indexer's published packages (delivery.PackagesBucket, ADR 0593 §2); unset reads none.
// PackagesState is the indexer's published packages (PackagesBucket, ADR 0593 §2); unset reads none.
PackagesState StateRead
// GraphState is the indexer's module graph (graph.Bucket, ADR 0603 §2), SourceState the gate's source and
// ProvisionsState the provisioner's keys: what view_tiers reads (tiers.go). Unset reads none, said in the answer.
GraphState, SourceState, ProvisionsState StateRead
// Pending reads the indexer's waits through its tool indexer_pending (ADR 0633 §5); unset names no module held back.
Pending func() (takein.PendingAnswer, error)
// BuildLog reads the builder's log from a time (stdio.Log(delivery.BuildLogRead).Since); unset reads none.
// BuildLog reads the builder's log from a time (stdio.Log(builds.BuildLogRead).Since); unset reads none.
BuildLog LogSince
}
@@ -151,7 +158,7 @@ func onlyModule(raw json.RawMessage, module string) (json.RawMessage, error) {
if len(raw) == 0 {
return nil, nil
}
rc, err := delivery.DecodeReach(raw)
rc, err := viewstate.DecodeReach(raw)
if err != nil {
return nil, err
}
@@ -159,7 +166,7 @@ func onlyModule(raw json.RawMessage, module string) (json.RawMessage, error) {
if !ok {
return nil, nil
}
rc.Modules = map[string]delivery.ModuleReach{module: mr}
rc.Modules = map[string]viewstate.ModuleReach{module: mr}
var holds []string
for _, h := range rc.Holds {
if strings.HasPrefix(h, module+" ") {
@@ -175,7 +182,7 @@ func (r Reader) reach(repository string) (any, error) {
return nil, fmt.Errorf("the reach state cannot be read here")
}
if repository = strings.TrimSpace(repository); repository != "" {
key, err := delivery.RepositoryKey(repository)
key, err := trunk.RepositoryKey(repository)
if err != nil {
return nil, err
}
@@ -200,7 +207,7 @@ func (r Reader) reach(repository string) (any, error) {
// Module is the stored value of modules.<module>, exactly as the indexer wrote it.
func (r Reader) Module(module string) (json.RawMessage, error) {
module = strings.TrimSpace(module)
key, err := delivery.ModulesKey(module)
key, err := meshcatalogclient.ModulesKey(module)
if err != nil {
return nil, err
}
@@ -260,7 +267,7 @@ const (
// Candidate is the stored value of the candidates key of a group, exactly as the indexer wrote it.
func (r Reader) Candidate(group string) (json.RawMessage, error) {
key, err := delivery.CandidatesKey(strings.TrimSpace(group))
key, err := CandidatesKey(strings.TrimSpace(group))
if err != nil {
return nil, err
}
@@ -299,13 +306,13 @@ func (r Reader) Candidates(module string) (map[string]json.RawMessage, []string,
if len(raw) == 0 {
continue
}
group, perr := delivery.ParseCandidatesKey(k)
var c delivery.Candidate
group, perr := ParseCandidatesKey(k)
var c meshcatalog.CandidatesByGroupValue
if perr != nil || json.Unmarshal(raw, &c) != nil {
unreadable = append(unreadable, k)
continue
}
if module != "" && !slices.ContainsFunc(c.Pulls, func(p delivery.CandidatePull) bool { return slices.Contains(p.Modules, module) }) {
if module != "" && !slices.ContainsFunc(c.Pulls, func(p meshcatalog.CandidatesByGroupValuePullsItem) bool { return slices.Contains(p.Modules, module) }) {
continue
}
out[group] = raw
@@ -355,7 +362,7 @@ func (r Reader) get(key string) (json.RawMessage, uint64, error) {
}
func (r Reader) builderRow(key string) (BuilderRow, bool, error) {
module, fp, err := delivery.ParseBuilderBuildKey(key)
module, fp, err := builds.ParseBuilderBuildKey(key)
if err != nil {
return BuilderRow{}, false, nil // a key that is no build key is not a build
}
@@ -396,7 +403,7 @@ func (r Reader) BuilderBuilds(module, state string, limit int) (BuildsAnswer, er
if prefix != "" && !strings.HasPrefix(k, prefix) {
continue
}
if _, _, err := delivery.ParseBuilderBuildKey(k); err != nil {
if _, _, err := builds.ParseBuilderBuildKey(k); err != nil {
out.Unreadable = append(out.Unreadable, k)
continue
}
@@ -497,7 +504,7 @@ func (r Reader) BuilderBuild(module, fp2, commit string) (BuilderRow, error) {
}
fp2 = m.FP2
}
key, err := delivery.BuilderBuildKey(module, fp2)
key, err := builds.BuilderBuildKey(module, fp2)
if err != nil {
return BuilderRow{}, err
}
@@ -640,9 +647,9 @@ func (r Reader) Wants(node, module string) (WantsAnswer, error) {
out := WantsAnswer{Wants: map[string]json.RawMessage{}, Held: map[string]json.RawMessage{}}
if node != "" && module != "" {
// One key, read directly: no list of the bucket (a hold has no node, so none is shown).
key, err := delivery.WantKey(node, module)
key, err := meshwantsclient.WantKey(node, module)
if module == "node" {
key, err = delivery.WantNodeKey(node)
key, err = meshwantsclient.WantNodeKey(node)
}
if err != nil {
return WantsAnswer{}, err
@@ -666,20 +673,20 @@ func (r Reader) Wants(node, module string) (WantsAnswer, error) {
// Narrowed by the key before any value is read.
var matching []string
for _, k := range keys {
if n, m, err := delivery.ParseWantKey(k); err == nil {
if n, m, err := meshwantsclient.ParseWantKey(k); err == nil {
if (node == "" || n == node) && (module == "" || m == module) {
matching = append(matching, k)
}
continue
}
// A node's own want, want.<node>.node (ADR 0539 clause 6): listed with the wants, under the module name "node".
if n, err := delivery.ParseWantNodeKey(k); err == nil {
if n, err := meshwantsclient.ParseWantNodeKey(k); err == nil {
if (node == "" || n == node) && (module == "" || module == "node") {
matching = append(matching, k)
}
continue
}
if m, _, err := delivery.ParseHeldKey(k); err == nil {
if m, _, err := meshwantsclient.ParseHeldKey(k); err == nil {
if node == "" && (module == "" || m == module) {
matching = append(matching, k)
}
@@ -694,7 +701,7 @@ func (r Reader) Wants(node, module string) (WantsAnswer, error) {
}
out.Cut, out.Note = cut, cutNote(cut, len(matching))
for k, raw := range values {
if _, _, err := delivery.ParseHeldKey(k); err == nil {
if _, _, err := meshwantsclient.ParseHeldKey(k); err == nil {
out.Held[k] = raw
} else {
out.Wants[k] = raw
@@ -705,7 +712,7 @@ func (r Reader) Wants(node, module string) (WantsAnswer, error) {
// Want is the stored want of module on node.
func (r Reader) Want(node, module string) (json.RawMessage, error) {
key, err := delivery.WantKey(strings.TrimSpace(node), strings.TrimSpace(module))
key, err := meshwantsclient.WantKey(strings.TrimSpace(node), strings.TrimSpace(module))
if err != nil {
return nil, err
}
@@ -729,7 +736,7 @@ func (r Reader) kept(s StateRead, what, node, module string) (KeptAnswer, error)
out := KeptAnswer{Keys: map[string]json.RawMessage{}}
if node != "" && module != "" {
// One key, read directly: no list of the bucket.
key, err := delivery.HaveKey(node, module)
key, err := nodeengineclient.HaveKey(node, module)
if err != nil {
return KeptAnswer{}, err
}
@@ -752,7 +759,7 @@ func (r Reader) kept(s StateRead, what, node, module string) (KeptAnswer, error)
// Narrowed by the key before any value is read.
var matching []string
for _, k := range keys {
n, m, isNode, err := delivery.ParseHaveKey(k)
n, m, isNode, err := nodeengineclient.ParseHaveKey(k)
if err != nil {
out.Unreadable = append(out.Unreadable, k)
continue
@@ -784,7 +791,7 @@ func (r Reader) Haves(node, module string) (KeptAnswer, error) {
// s6b): whether every node's record names the vault's key.
const TrustsReadTool = "node_trusts"
// NodeTrusts is what one node's record says it trusts: its lines (delivery.Trusts) and whether they name the vault's key
// NodeTrusts is what one node's record says it trusts: its lines (meshvaultclient.Trusts) and whether they name the vault's key
// the vault publishes.
type NodeTrusts struct {
Trusts []string `json:"trusts"`
@@ -810,12 +817,12 @@ func (r Reader) Trusts() (TrustsAnswer, error) {
}
out := TrustsAnswer{Nodes: map[string]NodeTrusts{}, NotYet: []string{}}
if r.SignersState.Get != nil {
raw, err := r.SignersState.Get(delivery.SignersKeyKey)
raw, err := r.SignersState.Get(SignersKeyKey)
if err != nil {
return TrustsAnswer{}, err
}
if len(raw) > 0 {
k, err := delivery.DecodeSignerKey(raw)
k, err := meshvaultclient.DecodeSignerKey(raw)
if err != nil {
return TrustsAnswer{}, err
}
@@ -828,7 +835,7 @@ func (r Reader) Trusts() (TrustsAnswer, error) {
}
var records []string
for _, k := range keys {
if _, _, isNode, err := delivery.ParseHaveKey(k); err == nil && isNode {
if _, _, isNode, err := nodeengineclient.ParseHaveKey(k); err == nil && isNode {
records = append(records, k)
}
}
@@ -837,8 +844,8 @@ func (r Reader) Trusts() (TrustsAnswer, error) {
return TrustsAnswer{}, err
}
for key, raw := range values {
node := strings.TrimSuffix(key, "."+delivery.HaveNodeWord)
h, err := delivery.DecodeHaveNode(raw)
node := strings.TrimSuffix(key, "."+nodeengineclient.NodeWord)
h, err := nodeengineclient.DecodeHaveNode(raw)
if err != nil {
out.Unreadable = append(out.Unreadable, key)
continue
@@ -847,7 +854,7 @@ func (r Reader) Trusts() (TrustsAnswer, error) {
if h.Record != nil {
t.Trusts = h.Record.Trusts
}
t.TrustsVault = out.VaultKey != "" && delivery.TrustsKey(t.Trusts, delivery.SignerVault, out.VaultKey)
t.TrustsVault = out.VaultKey != "" && meshvaultclient.TrustsKey(t.Trusts, meshvaultclient.SignerVault, out.VaultKey)
out.Nodes[node] = t
if !t.TrustsVault {
out.NotYet = append(out.NotYet, node)
@@ -857,7 +864,7 @@ func (r Reader) Trusts() (TrustsAnswer, error) {
sort.Strings(out.Unreadable)
out.Every = out.VaultKey != "" && len(out.Nodes) > 0 && len(out.NotYet) == 0 && len(out.Unreadable) == 0
if out.VaultKey == "" {
out.Note = "the vault publishes no signing key yet (" + delivery.SignersRead + "), so no node can trust it"
out.Note = "the vault publishes no signing key yet (" + SignersRead + "), so no node can trust it"
}
return out, nil
}
@@ -874,7 +881,7 @@ const (
// HistoryRow is one ended build of the builder's log, with how long it took from its start (none when its start is not in
// what was read).
type HistoryRow struct {
delivery.BuildLogEntry
builds.BuildLogEntry
Seconds float64 `json:"seconds,omitempty"`
}
@@ -887,7 +894,7 @@ type HistoryAnswer struct {
}
// BuildHistory is every build of module (every module when empty) that ended at or after since, oldest first, each with its
// duration from the start the log holds of the same module and fingerprint before it (delivery.BuildDuration). An entry of
// duration from the start the log holds of the same module and fingerprint before it (builds.BuildDuration). An entry of
// another kind than a build's start or end is passed over, whatever its form; a build's entry that does not read is
// refused, naming its sequence.
func (r Reader) BuildHistory(module string, since time.Time) (HistoryAnswer, error) {
@@ -897,7 +904,7 @@ func (r Reader) BuildHistory(module string, since time.Time) (HistoryAnswer, err
}
keys := ""
if module = strings.TrimSpace(module); module != "" {
k, err := delivery.BuildLogKey(module)
k, err := builds.BuildLogKey(module)
if err != nil {
return out, err
}
@@ -905,38 +912,38 @@ func (r Reader) BuildHistory(module string, since time.Time) (HistoryAnswer, err
}
page, err := r.BuildLog(since, keys, MaxHistoryEntries)
if err != nil {
return out, fmt.Errorf("the builder's log %s from %s: %w", delivery.BuildLogRead, since.Format(time.RFC3339), err)
return out, fmt.Errorf("the builder's log %s from %s: %w", builds.BuildLogRead, since.Format(time.RFC3339), err)
}
if page == nil {
return out, nil
}
var entries []delivery.BuildLogEntry
var entries []builds.BuildLogEntry
for _, le := range page.Entries {
if !buildlog.IsBuildEntry(le.Value) {
continue // an entry of another kind (the old reference form's close, design 51) is no build
}
e, err := delivery.DecodeBuildLogEntry(le.Value)
e, err := builds.DecodeBuildLogEntry(le.Value)
if err != nil {
return out, fmt.Errorf("the builder's log %s, entry %d: %w", delivery.BuildLogRead, le.Sequence, err)
return out, fmt.Errorf("the builder's log %s, entry %d: %w", builds.BuildLogRead, le.Sequence, err)
}
entries = append(entries, e)
}
starts := map[string][]delivery.BuildLogEntry{}
starts := map[string][]builds.BuildLogEntry{}
for _, e := range entries {
if e.Event == delivery.BuildStartedEvent {
if e.Event == builds.BuildStartedEvent {
starts[e.Module+" "+e.FP] = append(starts[e.Module+" "+e.FP], e)
}
}
for _, e := range delivery.EndedSince(entries, since) {
for _, e := range builds.EndedSince(entries, since) {
row := HistoryRow{BuildLogEntry: e}
// the newest start of the same build at or before its end: a fingerprint built again later starts again after it
var start delivery.BuildLogEntry
var start builds.BuildLogEntry
for _, s := range starts[e.Module+" "+e.FP] {
if !s.At.After(e.At) && s.At.After(start.At) {
start = s
}
}
if d, ok := delivery.BuildDuration(start, e); ok {
if d, ok := builds.BuildDuration(start, e); ok {
row.Seconds = d.Seconds()
}
out.Builds = append(out.Builds, row)