Documentation
¶
Overview ¶
Package hostload refuses to admit more CPU-heavy WB work when the host is already saturated. Two orphaned fixture processes ran at 100% CPU for nearly seven days (2026-08-31, PIDs 43481/43483), driving load average to 7-12 on a shared machine; WB's merge-gate shards then failed unrelated candidates because everything on the box was starved for CPU. This package gives `wb run` and `wb worktree merge`/`prepare`/`resume` a floor below which they refuse new CPU-heavy work instead of piling onto an already-overloaded host.
The floor is disabled entirely — every check admits, and Resolve/Floor report a floor of 0 with a reason — in three cases, evaluated in this order:
- WB_ADMISSION_LOAD_FLOOR is set to a positive number: that number is the floor, and it wins even inside CI. This lets the dedicated host-load tests force real gating behavior no matter where they run.
- WB_ADMISSION_LOAD_FLOOR is set to "0" (or any non-positive number): disabled, reason "env". Env always overrides wb.yaml.
- Otherwise, CI is declared (CI=true or GITHUB_ACTIONS=true): disabled, reason "ci". GitHub's shared runners routinely report a load average of 8-10 on 4 vCPUs, so a fixed floor would refuse genuine `wb run` / `wb worktree merge` work inside CI workflows, not just protect a shared developer machine.
- Otherwise, wb.yaml sets admission.load_floor explicitly to 0: disabled, reason "config".
Absent all of the above, the floor is wb.yaml's admission.load_floor when positive, else the default of 2*runtime.NumCPU() — a 4-core developer Mac refuses new CPU-heavy work above a load average of 8.
Index ¶
Constants ¶
const EnvLoadFloor = "WB_ADMISSION_LOAD_FLOOR"
EnvLoadFloor overrides the resolved admission floor. A positive value sets the floor directly, taking priority over both wb.yaml and CI detection. A value of "0" (or any non-positive number) disables admission entirely. Unset defers to CI detection, then wb.yaml. See the package doc for the full resolution order.
Variables ¶
var ErrUnsupported = errors.New("hostload: 1-minute load average is not available on this platform")
ErrUnsupported is returned by a platform Reader that has no load-average source. Callers must treat it as "never refuse", not as a failure.
Functions ¶
func Check ¶
Check refuses admission when the host's 1-minute load average exceeds floor, unless allow is true (the caller passed --allow-saturated-host). floor <= 0 means admission is disabled (see Resolve/Disabled) and Check always admits, without even reading the load. read is normally nil, which selects System; tests inject a fake Reader. A Reader error (including ErrUnsupported) never blocks admission — an unreadable or unsupported load source fails open.
func Consumers ¶
Consumers returns up to n lines describing the busiest processes on the host, most CPU-hungry first, for use in a refusal message. Best-effort: any failure to run or parse `ps`, or a timeout, yields either an empty slice or a single one-line note — never an error, and never argv. It never blocks admission: the command is bounded by consumersTimeout regardless of how long a real `ps` would otherwise take.
func Disabled ¶
Disabled reports whether host-load admission is turned off entirely, and why. See Resolve for the reason values.
func Floor ¶
Floor resolves the load-average ceiling above which new CPU-heavy work is refused, discarding the disablement reason. Use Resolve when the reason needs to be recorded (e.g. on a receipt or runlog event).
func Resolve ¶
Resolve computes the admission floor and, when admission is disabled, names why: "env" (WB_ADMISSION_LOAD_FLOOR is 0 or negative), "ci" (CI/GITHUB_ACTIONS declared), or "config" (wb.yaml admission.load_floor: 0 explicitly). An empty reason means admission is active and floor is the ceiling Check should refuse above. See the package doc for resolution order — notably, a positive WB_ADMISSION_LOAD_FLOOR wins even inside CI. configPath "" resolves wbconfig.DefaultPath(). A missing or unparsable config is not an error here — it just keeps the default.