diff --git a/modules/mesh-build-go/cmd/mesh-build-go/announce.go b/modules/mesh-build-go/cmd/mesh-build-go/announce.go index 2543242e..2163bca1 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/announce.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/announce.go @@ -14,6 +14,7 @@ var Kept = []announce.State{ {Name: "toolchains", Readable: true}, {Name: "keys", Readable: true}, {Name: "steps", Readable: true}, + {Name: "pauses", Readable: true}, } // keepStates announces Kept as this module's (stdio.Keeps): main calls it before it serves. diff --git a/modules/mesh-build-go/cmd/mesh-build-go/asks.go b/modules/mesh-build-go/cmd/mesh-build-go/asks.go index 98e98a2c..f7ba3cea 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/asks.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/asks.go @@ -89,13 +89,13 @@ func (m *Module) Puller(steps []StepTool, source buildstep.AskSource) *buildstep } ask := m.askSteps(steps) var load func(string) ([]byte, error) - if m.ReadSteps.Get != nil { + if m.ReadPauses.Get != nil { load = func(key string) ([]byte, error) { - raw, err := m.ReadSteps.Get(key) + raw, err := m.ReadPauses.Get(key) return raw, err } } - return &buildstep.Puller{Source: source, Language: delivery.AskGo, Node: m.Node, Put: m.Steps, Load: load, + return &buildstep.Puller{Source: source, Language: delivery.AskGo, Node: m.Node, Put: m.Steps, PausePut: m.Pauses, Load: load, Capacity: capacity, WatchConfig: watch, Logf: m.Say, Run: func(ctx context.Context, a delivery.StepAsk) (any, error) { if err := m.Check(ctx); err != nil { diff --git a/modules/mesh-build-go/cmd/mesh-build-go/main.go b/modules/mesh-build-go/cmd/mesh-build-go/main.go index d9e0da20..93058f02 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/main.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/main.go @@ -40,6 +40,8 @@ func main() { Emit: func(t string, b any) error { return stdio.Emit(t, b) }, Steps: stdio.State(delivery.StepsState).Put, ReadSteps: readOf(stdio.State(delivery.StepsState)), + Pauses: stdio.State(delivery.PausesState).Put, + ReadPauses: readOf(stdio.State(delivery.PausesState)), ReadToolchainsState: readOf(stdio.State(delivery.ToolchainsState)), Ctx: ctx, Say: logf, diff --git a/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go b/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go index 7ddfe322..dcf6fd8b 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go @@ -92,9 +92,13 @@ func TestManifestKeepsItsStatesClaimsItsBuildSeatAndDeclaresItsHealthTool(t *tes states := []string{} for _, s := range m.State { states = append(states, s.Name) + // A step's key is per step and dropped after its age, so the bucket cannot fill; a pause has no age. + if (s.Name == "steps") != (s.TTLSeconds > 0) { + t.Errorf("state %s has ttl-seconds %d: only steps has an age", s.Name, s.TTLSeconds) + } } slices.Sort(states) - if want := []string{"keys", "steps", "toolchains"}; !slices.Equal(states, want) { + if want := []string{"keys", "pauses", "steps", "toolchains"}; !slices.Equal(states, want) { t.Errorf("state = %v, want %v", states, want) } if len(m.Claims) != 1 || m.Claims[0].Name != Seat { diff --git a/modules/mesh-build-go/cmd/mesh-build-go/module.go b/modules/mesh-build-go/cmd/mesh-build-go/module.go index 48903962..f7ef5317 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/module.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/module.go @@ -29,6 +29,9 @@ type Module struct { Toolchains, Steps buildstep.Put // ReadSteps and ReadToolchainsState read those two states back for the read tools (issue 1562). ReadSteps, ReadToolchainsState StateRead + // Pauses is the Put of the pauses state, which keeps the node's pause key without an age; ReadPauses reads it back. + Pauses buildstep.Put + ReadPauses StateRead // Emit tells the bus an event (stdio.Emit); nil emits nothing. The guard emits toolchain.reported after each write of // the toolchains key, so the indexer, which holds no timer, learns that the bucket exists (issue 1444). Emit func(eventType string, body any) error diff --git a/modules/mesh-build-go/go.mod b/modules/mesh-build-go/go.mod index d7662595..f2ce3bf2 100644 --- a/modules/mesh-build-go/go.mod +++ b/modules/mesh-build-go/go.mod @@ -3,7 +3,7 @@ module meshbuildgo go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8 github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 diff --git a/modules/mesh-build-go/go.sum b/modules/mesh-build-go/go.sum index 6481c96b..2bc2434a 100644 --- a/modules/mesh-build-go/go.sum +++ b/modules/mesh-build-go/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373 h1:Bykd8L6nHGNsvpHk3hLMeOct75UwlboHxasqB4cGKvQ= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8 h1:x4mvY7yiGTP5lnzxbiwyj1o24p05hAmzZP7xHg3XX2M= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= diff --git a/modules/mesh-build-go/module.json b/modules/mesh-build-go/module.json index 600345e3..6346a6ad 100644 --- a/modules/mesh-build-go/module.json +++ b/modules/mesh-build-go/module.json @@ -10,7 +10,7 @@ "state": [ "toolchains", "keys", - "steps" + {"name": "steps", "ttl-seconds": 172800}, "pauses" ], "claims": [ { diff --git a/modules/mesh-build-image/cmd/mesh-build-image/announce.go b/modules/mesh-build-image/cmd/mesh-build-image/announce.go index 616e78c1..ee48ed0a 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/announce.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/announce.go @@ -13,6 +13,7 @@ import ( var Kept = []announce.State{ {Name: "keys", Readable: true}, {Name: "steps", Readable: true}, + {Name: "pauses", Readable: true}, } // keepStates announces Kept as this module's (stdio.Keeps): main calls it before it serves. diff --git a/modules/mesh-build-image/cmd/mesh-build-image/asks.go b/modules/mesh-build-image/cmd/mesh-build-image/asks.go index fe987adc..a62e583d 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/asks.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/asks.go @@ -46,10 +46,10 @@ func (m *Module) Puller(steps []StepTool, source buildstep.AskSource) *buildstep } ask := m.askSteps(steps) var load func(string) ([]byte, error) - if m.ReadSteps.Get != nil { - load = func(key string) ([]byte, error) { return m.ReadSteps.Get(key) } + if m.ReadPauses.Get != nil { + load = func(key string) ([]byte, error) { return m.ReadPauses.Get(key) } } - return &buildstep.Puller{Source: source, Language: delivery.AskImage, Node: m.Node, Put: m.Steps, Load: load, + return &buildstep.Puller{Source: source, Language: delivery.AskImage, Node: m.Node, Put: m.Steps, PausePut: m.Pauses, Load: load, Capacity: capacity, WatchConfig: watch, Logf: m.Say, Run: func(ctx context.Context, a delivery.StepAsk) (any, error) { if err := m.Check(ctx); err != nil { diff --git a/modules/mesh-build-image/cmd/mesh-build-image/main.go b/modules/mesh-build-image/cmd/mesh-build-image/main.go index 1fc279c3..2d4e6aa2 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/main.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/main.go @@ -29,13 +29,15 @@ func logf(format string, a ...any) { fmt.Fprintf(os.Stderr, "[mesh-build-image] func main() { ctx := context.Background() m := &Module{ - Node: strings.TrimSpace(os.Getenv("MESH_NODE")), - Steps: stdio.State(delivery.StepsState).Put, - ReadSteps: readOf(stdio.State(delivery.StepsState)), - Ctx: ctx, - Say: logf, - Work: WorkDir, - Store: StoreDir, + Node: strings.TrimSpace(os.Getenv("MESH_NODE")), + Steps: stdio.State(delivery.StepsState).Put, + ReadSteps: readOf(stdio.State(delivery.StepsState)), + Pauses: stdio.State(delivery.PausesState).Put, + ReadPauses: readOf(stdio.State(delivery.PausesState)), + Ctx: ctx, + Say: logf, + Work: WorkDir, + Store: StoreDir, } m.Floor = floorOf(m.Node) if u, err := user.Current(); err == nil { diff --git a/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go b/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go index b8be9de0..9b424a22 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go @@ -97,9 +97,13 @@ func TestManifestKeepsItsStatesClaimsItsBuildSeatAndDeclaresItsHealthTool(t *tes states := []string{} for _, s := range m.State { states = append(states, s.Name) + // A step's key is per step and dropped after its age, so the bucket cannot fill; a pause has no age. + if (s.Name == "steps") != (s.TTLSeconds > 0) { + t.Errorf("state %s has ttl-seconds %d: only steps has an age", s.Name, s.TTLSeconds) + } } slices.Sort(states) - if want := []string{"keys", "steps"}; !slices.Equal(states, want) { + if want := []string{"keys", "pauses", "steps"}; !slices.Equal(states, want) { t.Errorf("state = %v, want %v", states, want) } if len(m.Claims) != 1 || m.Claims[0].Name != Seat || !slices.Equal(m.Claims[0].Serves, []string{"current", "pause", "resume"}) { diff --git a/modules/mesh-build-image/cmd/mesh-build-image/module.go b/modules/mesh-build-image/cmd/mesh-build-image/module.go index 71d3d1af..76a14c71 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/module.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/module.go @@ -24,6 +24,9 @@ type Module struct { // Steps is the Put of the steps state; ReadSteps reads it back for the read tools. Steps buildstep.Put ReadSteps StateRead + // Pauses is the Put of the pauses state, which keeps the node's pause key without an age; ReadPauses reads it back. + Pauses buildstep.Put + ReadPauses StateRead // Ctx is the process's context, which a step runs under (the tool call's is cut at 30 s, the step's is not). Ctx context.Context Say func(format string, a ...any) diff --git a/modules/mesh-build-image/go.mod b/modules/mesh-build-image/go.mod index 12c90763..d61c482e 100644 --- a/modules/mesh-build-image/go.mod +++ b/modules/mesh-build-image/go.mod @@ -3,7 +3,7 @@ module meshbuildimage go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-build-image/go.sum b/modules/mesh-build-image/go.sum index f9d4f1cd..8a877fdd 100644 --- a/modules/mesh-build-image/go.sum +++ b/modules/mesh-build-image/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373 h1:Bykd8L6nHGNsvpHk3hLMeOct75UwlboHxasqB4cGKvQ= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8 h1:x4mvY7yiGTP5lnzxbiwyj1o24p05hAmzZP7xHg3XX2M= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8/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-build-image/module.json b/modules/mesh-build-image/module.json index cfe8489f..6e25dbfa 100644 --- a/modules/mesh-build-image/module.json +++ b/modules/mesh-build-image/module.json @@ -9,7 +9,7 @@ ], "state": [ "keys", - "steps" + {"name": "steps", "ttl-seconds": 172800}, "pauses" ], "claims": [ { diff --git a/modules/mesh-build-node/cmd/mesh-build-node/announce.go b/modules/mesh-build-node/cmd/mesh-build-node/announce.go index 2543242e..2163bca1 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/announce.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/announce.go @@ -14,6 +14,7 @@ var Kept = []announce.State{ {Name: "toolchains", Readable: true}, {Name: "keys", Readable: true}, {Name: "steps", Readable: true}, + {Name: "pauses", Readable: true}, } // keepStates announces Kept as this module's (stdio.Keeps): main calls it before it serves. diff --git a/modules/mesh-build-node/cmd/mesh-build-node/asks.go b/modules/mesh-build-node/cmd/mesh-build-node/asks.go index 2e7c4f2e..7926b195 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/asks.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/asks.go @@ -54,10 +54,10 @@ func (m *Module) Puller(steps []StepTool, source buildstep.AskSource) *buildstep } ask := m.askSteps(steps) var load func(string) ([]byte, error) - if m.ReadSteps.Get != nil { - load = func(key string) ([]byte, error) { return m.ReadSteps.Get(key) } + if m.ReadPauses.Get != nil { + load = func(key string) ([]byte, error) { return m.ReadPauses.Get(key) } } - return &buildstep.Puller{Source: source, Language: delivery.AskNode, Node: m.Node, Put: m.Steps, Load: load, + return &buildstep.Puller{Source: source, Language: delivery.AskNode, Node: m.Node, Put: m.Steps, PausePut: m.Pauses, Load: load, Capacity: capacity, WatchConfig: watch, Logf: m.Say, Run: func(ctx context.Context, a delivery.StepAsk) (any, error) { if err := m.Prepare(ctx); err != nil { diff --git a/modules/mesh-build-node/cmd/mesh-build-node/main.go b/modules/mesh-build-node/cmd/mesh-build-node/main.go index 0856bd77..94344992 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/main.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/main.go @@ -46,6 +46,8 @@ func main() { Emit: func(t string, b any) error { return stdio.Emit(t, b) }, Steps: stdio.State(delivery.StepsState).Put, ReadSteps: readOf(stdio.State(delivery.StepsState)), + Pauses: stdio.State(delivery.PausesState).Put, + ReadPauses: readOf(stdio.State(delivery.PausesState)), ReadToolchainsState: readOf(stdio.State(delivery.ToolchainsState)), Work: WorkDir, Run: forgekey.ExecRunnerClean(0), diff --git a/modules/mesh-build-node/cmd/mesh-build-node/manifest_test.go b/modules/mesh-build-node/cmd/mesh-build-node/manifest_test.go index 8b9ff5ec..39860aa0 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/manifest_test.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/manifest_test.go @@ -94,9 +94,13 @@ func TestManifestKeepsItsStatesClaimsItsBuildSeatAndDeclaresItsHealthTool(t *tes states := []string{} for _, s := range m.State { states = append(states, s.Name) + // A step's key is per step and dropped after its age, so the bucket cannot fill; a pause has no age. + if (s.Name == "steps") != (s.TTLSeconds > 0) { + t.Errorf("state %s has ttl-seconds %d: only steps has an age", s.Name, s.TTLSeconds) + } } slices.Sort(states) - if want := []string{"keys", "steps", "toolchains"}; !slices.Equal(states, want) { + if want := []string{"keys", "pauses", "steps", "toolchains"}; !slices.Equal(states, want) { t.Errorf("state = %v, want %v", states, want) } if len(m.Claims) != 1 || m.Claims[0].Name != Seat || !slices.Equal(m.Claims[0].Serves, []string{"current", "pause", "resume"}) { diff --git a/modules/mesh-build-node/cmd/mesh-build-node/module.go b/modules/mesh-build-node/cmd/mesh-build-node/module.go index a464a88e..1517b159 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/module.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/module.go @@ -43,6 +43,9 @@ type Module struct { Toolchains, Steps buildstep.Put // ReadSteps and ReadToolchainsState read those two states back for the read tools (issue 1562). ReadSteps, ReadToolchainsState StateRead + // Pauses is the Put of the pauses state, which keeps the node's pause key without an age; ReadPauses reads it back. + Pauses buildstep.Put + ReadPauses StateRead // Emit tells the bus an event (stdio.Emit); nil emits nothing. The guard emits toolchain.reported after each write of // the toolchains key, so the indexer, which holds no timer, learns that the bucket exists (issue 1444). Emit func(eventType string, body any) error diff --git a/modules/mesh-build-node/go.mod b/modules/mesh-build-node/go.mod index e17288f0..80306322 100644 --- a/modules/mesh-build-node/go.mod +++ b/modules/mesh-build-node/go.mod @@ -3,7 +3,7 @@ module meshbuildnode go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8 github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-build-node/go.sum b/modules/mesh-build-node/go.sum index 88f93b50..e6f92511 100644 --- a/modules/mesh-build-node/go.sum +++ b/modules/mesh-build-node/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373 h1:Bykd8L6nHGNsvpHk3hLMeOct75UwlboHxasqB4cGKvQ= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025164403-a8fbabbfc373/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8 h1:x4mvY7yiGTP5lnzxbiwyj1o24p05hAmzZP7xHg3XX2M= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261025175617-518dae5ec9c8/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= diff --git a/modules/mesh-build-node/module.json b/modules/mesh-build-node/module.json index 25f858eb..993fb7a1 100644 --- a/modules/mesh-build-node/module.json +++ b/modules/mesh-build-node/module.json @@ -10,7 +10,7 @@ "state": [ "toolchains", "keys", - "steps" + {"name": "steps", "ttl-seconds": 172800}, "pauses" ], "claims": [ {