From c47afd8f4b88ff5aacb764411cff7f33d6cbab73 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 26 Oct 2026 21:20:22 +0100 Subject: [PATCH] build_usage says a seat's build hours, and when it is outside them A build module's capacity. now carries its node's build window (the operator, 2026-10-26: g14 builds only from 18:00 to 06:00); the seat shows it, outside it says it takes nothing new, and a value the module cannot read shows as any hour with the value and why. The checker's and the view's SDK pin moves to mesh-sdk d00dac1. --- modules/mesh-delivery-checker/go.mod | 2 +- modules/mesh-delivery-checker/go.sum | 4 +-- modules/mesh-delivery-view/go.mod | 2 +- modules/mesh-delivery-view/go.sum | 4 +-- .../mesh-delivery-view/internal/view/usage.go | 27 ++++++++++++++----- .../internal/view/usage_test.go | 11 ++++++++ 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/modules/mesh-delivery-checker/go.mod b/modules/mesh-delivery-checker/go.mod index cc0ac5a..a92d288 100644 --- a/modules/mesh-delivery-checker/go.mod +++ b/modules/mesh-delivery-checker/go.mod @@ -3,7 +3,7 @@ module mesh-delivery-checker go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026185254-02f50bd9d642 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202137-d00dac140b03 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-delivery-checker/go.sum b/modules/mesh-delivery-checker/go.sum index 9e114f3..cffc507 100644 --- a/modules/mesh-delivery-checker/go.sum +++ b/modules/mesh-delivery-checker/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026185254-02f50bd9d642 h1:mSBxF9KgIJyNL0gOKYq5naWewUj2yazU/tGOh12Tze0= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026185254-02f50bd9d642/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202137-d00dac140b03 h1:QIcGyV96AHZ6t/4AgBDlUOcs5tq40PppC7pwEpmzZco= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202137-d00dac140b03/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/modules/mesh-delivery-view/go.mod b/modules/mesh-delivery-view/go.mod index c44cc9b..9fb5a30 100644 --- a/modules/mesh-delivery-view/go.mod +++ b/modules/mesh-delivery-view/go.mod @@ -3,7 +3,7 @@ module mesh-delivery-view go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026185254-02f50bd9d642 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202137-d00dac140b03 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-delivery-view/go.sum b/modules/mesh-delivery-view/go.sum index 9e114f3..cffc507 100644 --- a/modules/mesh-delivery-view/go.sum +++ b/modules/mesh-delivery-view/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026185254-02f50bd9d642 h1:mSBxF9KgIJyNL0gOKYq5naWewUj2yazU/tGOh12Tze0= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026185254-02f50bd9d642/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202137-d00dac140b03 h1:QIcGyV96AHZ6t/4AgBDlUOcs5tq40PppC7pwEpmzZco= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026202137-d00dac140b03/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/modules/mesh-delivery-view/internal/view/usage.go b/modules/mesh-delivery-view/internal/view/usage.go index 7849d80..35e1fbc 100644 --- a/modules/mesh-delivery-view/internal/view/usage.go +++ b/modules/mesh-delivery-view/internal/view/usage.go @@ -108,8 +108,14 @@ type SeatUsage struct { // Configured is mesh-config's capacity when the module says it judges by a lower one (capacity. of its pauses // state: the configured capacity bounded by its node's build CPU, issue 1806's follow-up); Capacity is then the // module's and CapacityFrom its why. - Configured int `json:"configured,omitempty"` - Paused bool `json:"paused"` + Configured int `json:"configured,omitempty"` + // BuildHours is the node's build window as the module says it (HH:MM-HH:MM and its zone), absent when it builds at any + // hour; OutsideHours says the module judged the time outside it, so it takes nothing new (the operator, 2026-10-26). + BuildHours string `json:"build_hours,omitempty"` + OutsideHours bool `json:"outside_hours,omitempty"` + // BuildHoursFault is why the module cannot read its node's build-hours value, naming it: it then builds at any hour. + BuildHoursFault string `json:"build_hours_fault,omitempty"` + Paused bool `json:"paused"` // Eligible says it takes asks: it holds the seat, has a capacity above 0 and is not paused; WhyNot says why not. // EligibleKnown is false when this tool cannot tell (it cannot read mesh-config's capacities): Eligible is then // absent, never false, and WhyNot starts "not known: ". @@ -468,10 +474,17 @@ func (u UsageReader) Usage() UsageAnswer { s.Capacity = (&buildrun.Places{Capacity: caps}).CapacityOf(node) s.CapacityFrom = fmt.Sprintf("the modules' default %q: mesh-config holds no resolved value for %s on %s", buildstep.DefaultCapacities, s.Module, node) } - if c, ok := judged[node+"."+lang]; ok && s.Holds && unknown == "" && !isBad && c.Configured == s.Capacity && c.Effective != c.Configured { - // The module running on the node judges by less than mesh-config gives: its node's build CPU bounds it. - s.Configured, s.Capacity = s.Capacity, c.Effective - s.CapacityFrom = fmt.Sprintf("%s, as %s on %s judges it (said %s)", c.Why, s.Module, node, c.At.UTC().Format(time.RFC3339)) + if c, ok := judged[node+"."+lang]; ok && s.Holds && unknown == "" && !isBad && c.Configured == s.Capacity { + // The module running on the node says its build hours, and judges by less than mesh-config gives when its + // node's build CPU bounds it or the time is outside its build hours. + s.BuildHours, s.OutsideHours = c.BuildHours, c.OutsideHours + if c.BuildHoursFault != "" { + s.BuildHours, s.BuildHoursFault = "any hour", c.BuildHoursFault + } + if c.Effective != c.Configured { + s.Configured, s.Capacity = s.Capacity, c.Effective + s.CapacityFrom = fmt.Sprintf("%s, as %s on %s judges it (said %s)", c.Why, s.Module, node, c.At.UTC().Format(time.RFC3339)) + } } s.Paused = paused[node+"."+lang] s.EligibleKnown = true @@ -487,6 +500,8 @@ func (u UsageReader) Usage() UsageAnswer { s.WhyNot = "not known: this tool cannot read its capacity (" + unknown + ")" case isBad: s.WhyNot = "its capacity on " + node + " cannot be read, so its puller uses 0" + case s.OutsideHours: + s.WhyNot = "outside its build hours " + s.BuildHours + " on " + node + ": it takes nothing new until they open" case s.Capacity == 0: s.WhyNot = "its capacity on " + node + " is 0" } diff --git a/modules/mesh-delivery-view/internal/view/usage_test.go b/modules/mesh-delivery-view/internal/view/usage_test.go index 78cab03..dc33ff1 100644 --- a/modules/mesh-delivery-view/internal/view/usage_test.go +++ b/modules/mesh-delivery-view/internal/view/usage_test.go @@ -206,6 +206,17 @@ func TestBuildUsageAnswersEveryNodesUseFromTheStates(t *testing.T) { if sa := seatOf(t, bound, "ace", "node-build-go"); sa.Capacity != 2 || sa.Configured != 0 { t.Errorf("a module's word older than mesh-config's value is not taken: %+v", sa) } + // The operator, 2026-10-26: outside its build hours the seat takes nothing new, and says so. + u.Pauses["go"] = states(map[string]string{"capacity.shanks": `{"v":1,"effective":0,"configured":2,"build-hours":"18:00-06:00 CET","outside-hours":true,"why":"0, outside its build hours 18:00-06:00 CET until 18:00 (otherwise 2)","at":"2026-10-26T11:00:00Z"}`}) + if so := seatOf(t, u.Usage(), "shanks", "node-build-go"); so.Capacity != 0 || !so.OutsideHours || so.Eligible == nil || *so.Eligible || + so.WhyNot != "outside its build hours 18:00-06:00 CET on shanks: it takes nothing new until they open" { + t.Errorf("a seat outside its build hours: %+v", so) + } + // A build-hours value the module cannot read: it builds at any hour, and the seat says the value and why. + u.Pauses["go"] = states(map[string]string{"capacity.shanks": `{"v":1,"effective":2,"configured":2,"build-hours-fault":"the build hours \"shanks=18:00-6\": \"6\" is not a time HH:MM","why":"2; at any hour, because its build hours cannot be read","at":"2026-10-26T11:00:00Z"}`}) + if sf := seatOf(t, u.Usage(), "shanks", "node-build-go"); sf.BuildHours != "any hour" || !strings.Contains(sf.BuildHoursFault, "shanks=18:00-6") || sf.Eligible == nil || !*sf.Eligible { + t.Errorf("a seat whose build hours cannot be read: %+v", sf) + } if len(bound.TriesRunning) != 1 || len(bound.TriesRunning[0].Asks) != 1 || !strings.Contains(string(bound.TriesRunning[0].Steps), "unit: tests") || strings.Contains(strings.Join(bound.Notes, " | "), "name no ask yet") { t.Errorf("a running try naming its asks: %+v, notes %v", bound.TriesRunning, bound.Notes)