Say checked, healer-acted and act-recorded on their seats' subjects, where their consumers hear them, and pin mesh-sdk fbd00c8 (issues 1952, 1953)
stdio.Emit put them on the module's subject, which no consumer of a seat's event hears. The manifests no longer list a seat's events as the module's own, which the SDK now refuses. mesh-hand-acts takes its act layout and names from mesh-sdk's handacts, and counts a repeated cause by its Repair rule.
This commit is contained in:
@@ -40,8 +40,8 @@ func (runtimeStore) Keys(state string) ([]string, error) { return stdio.State(st
|
||||
// NewChecker is the self-check over the runtime.
|
||||
func NewChecker() *Checker {
|
||||
return &Checker{Store: runtimeStore{}, Registry: Registry(), Now: time.Now, Logf: logf, Host: os.Getenv("MESH_NODE"),
|
||||
Ask: func(key string, body any) (json.RawMessage, error) { return stdio.Ask(key, body) },
|
||||
Emit: func(event string, body any) error { return stdio.Emit(event, body) }}
|
||||
Ask: func(key string, body any) (json.RawMessage, error) { return stdio.Ask(key, body) },
|
||||
Publish: stdio.SeatPublish}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -47,7 +47,8 @@ func TestTheManifestSaysWhatTheCodeDoes(t *testing.T) {
|
||||
if len(m.Claims) != 1 || m.Claims[0].Name != Seat || m.Claims[0].Scope != "mesh" || !slices.Equal(m.Claims[0].Serves, Verbs) {
|
||||
t.Errorf("claims %+v, want %s at mesh scope serving %v", m.Claims, Seat, Verbs)
|
||||
}
|
||||
if !slices.Equal(m.Emits, []string{CheckedEvent}) {
|
||||
// checked is the seat's event, said on the seat's subject: a module lists no event of a seat it claims.
|
||||
if len(m.Emits) != 0 {
|
||||
t.Errorf("emits %v", m.Emits)
|
||||
}
|
||||
if !slices.Equal(m.Invokes, []string{StreamsTool, ClosedTool, SignalsVerb}) {
|
||||
|
||||
@@ -32,6 +32,9 @@ const (
|
||||
VerdictsState = "verdicts"
|
||||
LastKey = "last"
|
||||
CheckedEvent = health.EventChecked
|
||||
// CheckedSubject is where the seat says it: a seat's events are on mesh.seat.<seat>.event.<name>, which its
|
||||
// consumers hear (catalogue.SeatSays).
|
||||
CheckedSubject = "mesh.seat." + Seat + ".event." + CheckedEvent
|
||||
)
|
||||
|
||||
// The clocks: the self-check's run is the one timer among the four holders (ADR 0564 §1).
|
||||
@@ -83,9 +86,10 @@ type (
|
||||
|
||||
// Checker is the self-check: the registry and what its probes reach.
|
||||
type Checker struct {
|
||||
Store Store
|
||||
Ask func(key string, body any) (json.RawMessage, error)
|
||||
Emit func(event string, body any) error
|
||||
Store Store
|
||||
Ask func(key string, body any) (json.RawMessage, error)
|
||||
// Publish says a seat event on its subject, de-duplicated by id (stdio.SeatPublish).
|
||||
Publish func(subject string, body any, id string) error
|
||||
Now func() time.Time
|
||||
Logf func(format string, args ...any)
|
||||
Host string
|
||||
@@ -328,10 +332,10 @@ func (c *Checker) keep(run Run) {
|
||||
if err := c.Store.Put(VerdictsState, run.Run, Overview(run)); err != nil {
|
||||
c.Logf("[%s] the run %s is not kept among the week's verdicts: %v", Module, run.Run, err)
|
||||
}
|
||||
if c.Emit == nil {
|
||||
if c.Publish == nil {
|
||||
return
|
||||
}
|
||||
if err := c.Emit(CheckedEvent, run); err != nil {
|
||||
if err := c.Publish(CheckedSubject, run, run.Run); err != nil {
|
||||
c.mu.Lock()
|
||||
c.unsaid++
|
||||
c.mu.Unlock()
|
||||
|
||||
@@ -81,9 +81,9 @@ func checker(store *memStore, registry ...Probe) (*Checker, *[]string) {
|
||||
now := time.Date(2026, 10, 29, 21, 0, 0, 0, time.UTC)
|
||||
c := &Checker{Store: store, Registry: registry, Host: "novox", Logf: func(string, ...any) {},
|
||||
Now: func() time.Time { now = now.Add(time.Second); return now },
|
||||
Emit: func(event string, body any) error {
|
||||
Publish: func(subject string, body any, id string) error {
|
||||
raw, _ := json.Marshal(body)
|
||||
said = append(said, event+" "+string(raw))
|
||||
said = append(said, subject+" "+id+" "+string(raw))
|
||||
return nil
|
||||
}}
|
||||
return c, &said
|
||||
@@ -147,11 +147,14 @@ func TestARunWritesFindingsAsTheyChange(t *testing.T) {
|
||||
if keys, _ := store.Keys(VerdictsState); len(keys) != len(steps) {
|
||||
t.Errorf("verdicts kept %d runs, want %d", len(keys), len(steps))
|
||||
}
|
||||
if len(*said) != len(steps) || !strings.HasPrefix((*said)[0], CheckedEvent+" ") {
|
||||
// Said on the seat's subject, where its consumers hear it, de-duplicated by the run's id.
|
||||
if len(*said) != len(steps) || !strings.HasPrefix((*said)[0], "mesh.seat.mesh-self-check.event.checked doctor-") {
|
||||
t.Fatalf("said %v", *said)
|
||||
}
|
||||
_, rest, _ := strings.Cut((*said)[0], " ")
|
||||
_, rest, _ = strings.Cut(rest, " ")
|
||||
var body map[string]any
|
||||
_ = json.Unmarshal([]byte(strings.TrimPrefix((*said)[0], CheckedEvent+" ")), &body)
|
||||
_ = json.Unmarshal([]byte(rest), &body)
|
||||
for _, field := range []string{"run", "at", "started", "took", "interval-seconds", "counts", "probes", "controller", "why"} {
|
||||
if _, ok := body[field]; !ok {
|
||||
t.Errorf("checked's body lacks %s, which doctor-heartbeat carries: %v", field, body)
|
||||
|
||||
@@ -146,6 +146,13 @@ func (p *player) handle(m wire) {
|
||||
err = kv.Delete(p.ctx, a.Key)
|
||||
}
|
||||
p.answer(m.ID, map[string]any{}, err)
|
||||
case "mesh/seat.publish":
|
||||
var e struct {
|
||||
Subject string `json:"subject"`
|
||||
Body json.RawMessage `json:"body"`
|
||||
}
|
||||
_ = json.Unmarshal(m.Params, &e)
|
||||
p.answer(m.ID, map[string]any{}, p.nc.Publish(e.Subject, e.Body))
|
||||
case "mesh/publish":
|
||||
var e struct {
|
||||
Key string `json:"key"`
|
||||
@@ -230,7 +237,7 @@ func TestTheSelfCheckWholeRunsOnTheBus(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
checked, err := nc.SubscribeSync("mesh.mod." + Module + ".event." + CheckedEvent)
|
||||
checked, err := nc.SubscribeSync("mesh.seat." + Seat + ".event." + CheckedEvent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-self-check
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029204453-69fcb6c1c1ba
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029211044-fbd00c89436c
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029204453-69fcb6c1c1ba h1:uXwkcQWgbu/UthizGHFaKPiA4NBVJgqL9q2jJnnGR1o=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029204453-69fcb6c1c1ba/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029211044-fbd00c89436c h1:Yd6AslGN7pCniQ9Q7ch05xAWHP57grXRoH3AsDQrSeY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029211044-fbd00c89436c/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=
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"emits": [
|
||||
"checked"
|
||||
],
|
||||
"invokes": [
|
||||
"nats.nats_streams",
|
||||
"nats.nats_closed_connections",
|
||||
|
||||
Reference in New Issue
Block a user