disk-load measures the items the node-engine keeps for its node, and composes nothing (ADR 0577)

It watches its node's keys of mesh-host_data instead of composing every module's items from
about 370 resolved keys per round, so a round no longer takes 30 to 45 minutes across the tunnel
and a manifest its mesh-sdk cannot judge no longer silences it. A changed key measures its module
at once; each round writes how far it got to the per-node state rounds, said by disk_round.
Pins mesh-sdk feat/data-items.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-01 00:15:14 +01:00
parent 444c2903af
commit b712123f2b
8 changed files with 307 additions and 64 deletions
+22 -24
View File
@@ -4,42 +4,52 @@
// filesystems' space and the processes doing the I/O — and changes nothing of the machine.
//
// It also measures the data items the modules of its node declare (ADR 0233) and keeps each reading and the item's
// seven-day peak as its own state `readings` (ADR 0571 clause 3), composed from the bus (no file).
// seven-day peak as its own state `readings` (ADR 0571 clause 3). It learns the items from the node-engine's state data,
// watching its own node's keys, and composes nothing (ADR 0577 clause 2); each round says how far it got in its state
// `rounds` (clause 3).
package main
import (
"context"
"fmt"
"os"
"strings"
"time"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/announce"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/compose/fromruntime"
)
func logf(format string, args ...any) { fmt.Fprintf(os.Stderr, "[disk-load] "+format+"\n", args...) }
// Kept is every state disk-load keeps, as it announces them: the readings, readable by restic, nfs-server, mounts and
// the self-check (their manifests' `reads`; checks/readable holds it), and the rounds, its own tools' alone.
var Kept = []announce.State{{Name: StateReadings, Readable: true}, {Name: StateRounds}}
func main() {
// Readable: restic, nfs-server, mounts and the self-check read it (their manifests' `reads`); checks/readable holds it.
if err := stdio.Keeps(announce.State{Name: StateReadings, Readable: true}); err != nil {
if err := stdio.Keeps(Kept...); err != nil {
logf("%v", err)
os.Exit(1)
}
node := os.Getenv("MESH_NODE")
k := &Keeper{Node: node, Store: busStore{}, Say: logf, Measurer: Measurer{Run: RootRunner, Now: time.Now},
Items: func(ctx context.Context) (map[string][]catalogue.PlacedDataItem, error) {
return placedItems(ctx, node)
}}
watched := &Watched{Node: node}
k := &Keeper{Node: node, Store: busStore{StateReadings}, Rounds: busStore{StateRounds}, Say: logf,
Measurer: Measurer{Run: RootRunner, Now: time.Now}, Items: watched.All}
if node != "" {
every := time.Hour
if d, err := time.ParseDuration(os.Getenv("MESH_DISK_MEASURE_EVERY")); err == nil && d >= time.Minute {
every = d
}
go k.Loop(context.Background(), every, 3*time.Minute)
ctx := context.Background()
go k.Work(ctx)
go func() {
<-stdio.Served() // the runtime's channel first: a watch is asked through it
if err := watched.Follow(k); err != nil {
logf("this machine's keys of the node-engine's data items cannot be watched, and nothing is measured: %v", err)
return
}
logf("watching this machine's keys of the node-engine's data items")
}()
go k.Loop(ctx, every, 3*time.Minute)
}
tools := append(Tools(Here()), ReadingTools(k)...)
// An empty name serves as the module the runtime names (MESH_SERVED_MODULE): disk-load.
@@ -48,15 +58,3 @@ func main() {
os.Exit(1)
}
}
// placedItems is every data item the modules placed on node declare, composed from the bus as the node composes itself.
func placedItems(ctx context.Context, node string) (map[string][]catalogue.PlacedDataItem, error) {
items, unplaced, err := frombus.DataItems(ctx, fromruntime.Reader(), frombus.Mesh{}, frombus.Scope{Node: node})
if err != nil {
return nil, err
}
if len(unplaced) > 0 {
logf("data items left out as not placeable: %s", strings.Join(unplaced, "; "))
}
return items, nil
}