From 436ab59214fa206f45fdbd434cea458c6c3ac328 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 16:48:32 +0100 Subject: [PATCH] =?UTF-8?q?view=20status:=20the=20conditions=20and=20the?= =?UTF-8?q?=20healers'=20attempts=20are=20read=20as=20the=20seats'=20types?= =?UTF-8?q?=20(mesh-conditions,=20mesh-healers)=20and=20ordered=20by=20mes?= =?UTF-8?q?hconditionsclient=20(ADR=200634=20=C2=A74;=20issue=201966)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i --- modules/mesh-delivery-view/go.mod | 3 +++ .../internal/view/status.go | 22 ++++++++++--------- .../internal/view/view_test.go | 14 +++++++----- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/modules/mesh-delivery-view/go.mod b/modules/mesh-delivery-view/go.mod index 3cb4b11a..786f7410 100644 --- a/modules/mesh-delivery-view/go.mod +++ b/modules/mesh-delivery-view/go.mod @@ -51,3 +51,6 @@ require ( replace git.novox.be/novox/mesh-delivery/sdk => ../../sdk replace git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein => ../mesh-delivery-indexer/takein +require git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000 +require git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000 +require git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhealers v0.0.0-00010101000000-000000000000 diff --git a/modules/mesh-delivery-view/internal/view/status.go b/modules/mesh-delivery-view/internal/view/status.go index ef2ba554..bb5c5e41 100644 --- a/modules/mesh-delivery-view/internal/view/status.go +++ b/modules/mesh-delivery-view/internal/view/status.go @@ -8,9 +8,11 @@ import ( "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient" "git.novox.be/novox/mesh-contracts/go/seats/nodeengine" + mcc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient" "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient" + mcseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" + healers "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhealers" "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient" - "git.novox.be/novox/mesh-sdk/go/health" "git.novox.be/novox/mesh-sdk/go/motion" ) @@ -28,8 +30,8 @@ const StatusTool = "view_status" // The states status reads, as the view's manifest names them. const ( - StatusConditionsState = health.KeeperModule + "." + health.ConditionsState - StatusAttemptsState = health.HealersModule + "." + health.AttemptsState + StatusConditionsState = mcseat.Seat + "." + mcseat.StateConditions + StatusAttemptsState = healers.Seat + "." + healers.StateAttempts StatusPresenceState = WatchmanModule + ".presence" StatusStuckState = WatchmanModule + ".stuck" ) @@ -115,17 +117,17 @@ func DeriveStatus(r StatusRead, now time.Time) Status { if raw, err := values(r.Conditions); err != nil { st.ConditionsUnread = "the condition keeper's conditions cannot be read: " + err.Error() } else { - var open []health.Condition + var open []mcseat.ConditionsByKeyValue for _, v := range raw { - var c health.Condition + var c mcseat.ConditionsByKeyValue if json.Unmarshal(v, &c) == nil && c.Key != "" { open = append(open, c) } } - health.Order(open) + mcc.Order(open) for _, c := range open { - st.Conditions = append(st.Conditions, StatusCondition{Key: c.Key, Severity: string(c.Severity), Machine: c.Subject.Machine, - Summary: c.Summary, Raised: c.Raised, Silenced: c.SilencedAt(now)}) + st.Conditions = append(st.Conditions, StatusCondition{Key: c.Key, Severity: c.Severity, Machine: c.Subject.Machine, + Summary: c.Summary, Raised: c.Raised, Silenced: mcc.SilencedAt(c, now)}) } } @@ -203,13 +205,13 @@ func DeriveStatus(r StatusRead, now time.Time) Status { st.HealsUnread = "mesh-healers' attempts cannot be read: " + err.Error() } else { for _, v := range raw { - var a health.Attempt + var a healers.AttemptsByAttemptValue if json.Unmarshal(v, &a) != nil || now.Sub(a.Begun) > HealsWithin { continue } outcome := a.Outcome if outcome == "" { - outcome = health.OutcomeActing + outcome = healers.AttemptsByAttemptValueOutcomeActing } st.Heals[outcome]++ } diff --git a/modules/mesh-delivery-view/internal/view/view_test.go b/modules/mesh-delivery-view/internal/view/view_test.go index 32c2182a..8d849fb3 100644 --- a/modules/mesh-delivery-view/internal/view/view_test.go +++ b/modules/mesh-delivery-view/internal/view/view_test.go @@ -10,12 +10,14 @@ import ( "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient" "git.novox.be/novox/mesh-contracts/go/seats/nodeengine" + mcc "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient" "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient" + mcseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" + healers "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhealers" "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" "git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient" "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" - "git.novox.be/novox/mesh-sdk/go/health" "git.novox.be/novox/mesh-sdk/go/keys" "git.novox.be/novox/mesh-sdk/go/motion" ) @@ -301,8 +303,8 @@ func statusDerivesEachPartFromItsBucket(t *testing.T) { fin := t0.Add(time.Minute) r := StatusRead{ Conditions: states(map[string]string{ - "machine.b.silent": enc(health.Condition{Key: "machine.b.silent", Severity: health.Warning, Summary: "b silent", Raised: t0}), - "core.doctor.self-check": enc(health.Condition{Key: "core.doctor.self-check", Severity: health.Urgent, Summary: "no run", Raised: t0.Add(time.Minute)}), + "machine.b.silent": enc(mcseat.ConditionsByKeyValue{Key: "machine.b.silent", Severity: mcc.Warning, Summary: "b silent", Raised: t0}), + "core.doctor.self-check": enc(mcseat.ConditionsByKeyValue{Key: "core.doctor.self-check", Severity: mcc.Urgent, Summary: "no run", Raised: t0.Add(time.Minute)}), }), Presence: states(map[string]string{"a": presence(true), "b": presence(false)}), Stuck: states(map[string]string{stuckWant: stuckOf(AssignerWantsBucket, "want.b.web", "b to run web", false), @@ -310,8 +312,8 @@ func statusDerivesEachPartFromItsBucket(t *testing.T) { Wants: states(map[string]string{"want.a.web": want(fp2), "want.a.mail": want(fp1), "want.b.web": want(fp2), "want.a.db": want(fp3)}), Haves: states(map[string]string{"a.web": have(fp1, nodeengineclient.PhaseRunning, nodeengineclient.HealthOK, ""), "a.mail": have(fp1, nodeengineclient.PhaseRunning, nodeengineclient.HealthOK, ""), "b.web": have(fp1, nodeengineclient.PhaseRunning, nodeengineclient.HealthOK, ""), "a.db": have(fp3, nodeengineclient.PhaseRunning, nodeengineclient.HealthFailed, "the unit failed")}), - Attempts: states(map[string]string{"1": enc(health.Attempt{Outcome: health.OutcomeActed, Begun: t0, Finished: &fin}), - "2": enc(health.Attempt{Outcome: health.OutcomeEscalated, Begun: t0}), "old": enc(health.Attempt{Outcome: health.OutcomeActed, Begun: now.Add(-8 * 24 * time.Hour)})}), + Attempts: states(map[string]string{"1": enc(healers.AttemptsByAttemptValue{Outcome: healers.AttemptsByAttemptValueOutcomeActed, Begun: t0, Finished: &fin}), + "2": enc(healers.AttemptsByAttemptValue{Outcome: healers.AttemptsByAttemptValueOutcomeEscalated, Begun: t0}), "old": enc(healers.AttemptsByAttemptValue{Outcome: healers.AttemptsByAttemptValueOutcomeActed, Begun: now.Add(-8 * 24 * time.Hour)})}), } st := DeriveStatus(r, now) if len(st.Conditions) != 2 || st.Conditions[0].Key != "core.doctor.self-check" || st.Conditions[1].Key != "machine.b.silent" { @@ -328,7 +330,7 @@ func statusDerivesEachPartFromItsBucket(t *testing.T) { if !reflect.DeepEqual(st.Moving, wantMoving) { t.Errorf("moving = %+v\nwant %+v", st.Moving, wantMoving) } - if !reflect.DeepEqual(st.Heals, map[string]int{health.OutcomeActed: 1, health.OutcomeEscalated: 1}) || st.Well { + if !reflect.DeepEqual(st.Heals, map[string]int{healers.AttemptsByAttemptValueOutcomeActed: 1, healers.AttemptsByAttemptValueOutcomeEscalated: 1}) || st.Well { t.Errorf("heals = %v, well %v", st.Heals, st.Well) } // A part it cannot read is said, and the mesh is not well; with nothing wrong and every part read it is.