From c85b150782ff913a0fb1938ff528f0ab7744741e Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 16:28:52 +0100 Subject: [PATCH] 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 --- .../mesh-delivery-view/internal/view/read.go | 93 ++++++++++--------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/modules/mesh-delivery-view/internal/view/read.go b/modules/mesh-delivery-view/internal/view/read.go index bfc21be3..f22bd87d 100644 --- a/modules/mesh-delivery-view/internal/view/read.go +++ b/modules/mesh-delivery-view/internal/view/read.go @@ -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., 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 (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)