A build seat's capacity follows its node's build CPU, and a running ask says its phases
Since the build CPU cap (issue 1806) shanks' mesh-build-go kept capacity 3 inside a 12-core slice: three full checks got about 4 cores each and ran past the 30-minute step bound (issue 1890). The puller now judges by min(configured, floor(slice quota cores / cores-per-step)), the quota read live from its cgroup, says it on change and writes capacity.<node> to the pauses state. A run's phases (fetch and merge, digest, tests) are logged with the ask id and written to its running step key; Asker.Wait hands every step value to a WithStepSeen hook.
This commit is contained in:
@@ -693,3 +693,54 @@ func DecodePause(data []byte) (Pause, error) {
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// CapacityKey is the key, in a build module's PausesState, where the module on node says the capacity it judges by
|
||||
// now and why: `capacity.<node>` (issue 1806's follow-up). The pauses state has no age, so the value stands until the
|
||||
// module writes another; a reader such as the delivery view's build_usage says it in place of the configured capacity.
|
||||
func CapacityKey(node string) (string, error) {
|
||||
if err := checkName("node", node); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "capacity." + node, nil
|
||||
}
|
||||
|
||||
// Capacity is a build seat's capacity on one node as its holder judges by it: the configured capacity (the module's
|
||||
// setting `capacity`), bounded by the cores its node's build slice gives (its CPU quota, read live) over the cores one
|
||||
// step needs (the module's setting `cores-per-step`). Effective is min(Configured, ByCPU) when a quota is known, else
|
||||
// Configured; one step at least while Configured is above zero, so a node whose quota is under one step's need still
|
||||
// builds, slowly.
|
||||
type Capacity struct {
|
||||
V int `json:"v"`
|
||||
Effective int `json:"effective"`
|
||||
Configured int `json:"configured"`
|
||||
// ConfiguredFrom says where Configured was read: mesh-config's value as the config watch handed it, or the settings
|
||||
// file.
|
||||
ConfiguredFrom string `json:"configured-from,omitempty"`
|
||||
// QuotaCores is the build slice's CPU quota in processors (cpu.max: 1200% is 12), 0 when none is known; QuotaFrom
|
||||
// says where it was read (the cgroup, or the share the composer gave) or why none is known.
|
||||
QuotaCores float64 `json:"quota-cores,omitempty"`
|
||||
QuotaFrom string `json:"quota-from"`
|
||||
// CoresPerStep is what one step of this module needs; ByCPU is floor(QuotaCores / CoresPerStep), at least 1, and 0
|
||||
// when no quota is known.
|
||||
CoresPerStep float64 `json:"cores-per-step"`
|
||||
ByCPU int `json:"by-cpu,omitempty"`
|
||||
// Why is the capacity in words: what bounds it.
|
||||
Why string `json:"why"`
|
||||
At time.Time `json:"at,omitzero"`
|
||||
}
|
||||
|
||||
// EncodeCapacity is c as JSON at Version.
|
||||
func EncodeCapacity(c Capacity) ([]byte, error) {
|
||||
c.V = Version
|
||||
c.At = c.At.UTC()
|
||||
return json.Marshal(c)
|
||||
}
|
||||
|
||||
// DecodeCapacity reads a capacity value; it refuses an unknown version (ErrUnknownVersion).
|
||||
func DecodeCapacity(data []byte) (Capacity, error) {
|
||||
var c Capacity
|
||||
if err := decode(data, &c); err != nil {
|
||||
return Capacity{}, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user