g14's Go builder sat idle at capacity 2 while delivery builds waited: a puller with no room waited on its wake alone, which only a pause, a resume or a step's end gives, and it read its capacity from the settings file only when woken. The puller now follows the module's config value capacity through the runtime's watch of what mesh-config resolved (stdio.WatchConfig), uses the value it hands, and wakes on each change: no timer, no file watch, and no wait for the node-engine to fill the file again. It says when it parks and when it wakes, with its capacity.
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package buildstep
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery/buildrun"
|
|
)
|
|
|
|
// CapacitySetting is the build modules' setting of each node's build capacity (novox/hq ADR 0525 §5): `<node>=<asks at
|
|
// once>` pairs separated by commas, as the builder's was (ADR 0485 §1). Each build module declares it with
|
|
// DefaultCapacities as its default, and the controller lays it into the module's settings file.
|
|
const CapacitySetting = "capacity"
|
|
|
|
// DefaultCapacities is the setting's default, the builder's before R4g: the control-node (novox) and the laptop (g14)
|
|
// build nothing.
|
|
const DefaultCapacities = "shanks=3,ace=2,g14=0,novox=0"
|
|
|
|
// NodeCapacity is node's build capacity, read from the module's settings file at path at every call, so a change takes
|
|
// effect at the next pull; with no path it reads fallback. A node the setting does not name runs one ask at a time (as
|
|
// the builder's did). A file or a setting that cannot be read gives 0 and says why: pulling on a setting nobody can read
|
|
// could build on a node that must not.
|
|
func NodeCapacity(path, fallback, node string, logf func(string, ...any)) func() int {
|
|
say := func(format string, args ...any) {
|
|
if logf != nil {
|
|
logf(format, args...)
|
|
}
|
|
}
|
|
return func() int {
|
|
setting := fallback
|
|
if path != "" {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
say("the build capacity cannot be read, so %s pulls nothing: %v", node, err)
|
|
return 0
|
|
}
|
|
var s map[string]any
|
|
if err := json.Unmarshal(raw, &s); err != nil {
|
|
say("the settings file %s is not JSON, so %s pulls nothing: %v", path, node, err)
|
|
return 0
|
|
}
|
|
setting, _ = s[CapacitySetting].(string)
|
|
}
|
|
n, err := capacityOf(setting, node)
|
|
if err != nil {
|
|
say("%v, so %s pulls nothing", err, node)
|
|
return 0
|
|
}
|
|
return n
|
|
}
|
|
}
|
|
|
|
// capacityOf is node's capacity in a setting's `<node>=<asks>` pairs: DefaultCapacity for a node it does not name.
|
|
func capacityOf(setting, node string) (int, error) {
|
|
caps, err := buildrun.ParseCapacity(setting)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("the build capacity: %w", err)
|
|
}
|
|
return (&buildrun.Places{Capacity: caps}).CapacityOf(node), nil
|
|
}
|