service_down nudges name the service again (V-534)
nudgeValues filled {service} from State.Fact("service_down"), an exact key
mavpoll stopped writing when per-monitor facts landed. The lookup could never
hit, so every variant carrying {service} was rejected as unfillable and the one
nameless variant was the only usable template, every time. A sev4 reaching him
on telegram said only that a service was down.
It now reads loop.DownServices, the same helper the rule fires on, so the
message cannot name a service that is up. Dropped the nameless variant and the
{since} one: service_down facts are keyed by monitor and the rule is
edge-triggered, so neither can fill. service_down joins routine and morning as
a family that always carries a name.
The tests passed through all of this because cand() built the pre-per-monitor
aggregate shape. downCand() builds what a tick actually produces.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011x5DgnExQ5XZy8TZPs5bot
This commit is contained in:
@@ -165,17 +165,25 @@ func nudgeValues(c loop.Candidate) map[string]string {
|
||||
vals := map[string]string{}
|
||||
rule := c.Rule.Name
|
||||
|
||||
// {service} — one fact per kuma monitor, keyed "service_down:<name>", so
|
||||
// the name lives in the key SUFFIX and there is no fact called plain
|
||||
// "service_down" to read. loop.DownServices is the same helper the rule
|
||||
// fired on, which is what stops the message naming a service that is up.
|
||||
// This used to read c.State.Fact(rule) — the pre-per-monitor aggregate —
|
||||
// and so never filled, leaving the one nameless variant as the only
|
||||
// fillable template every time (Vikunja #534).
|
||||
if down := loop.DownServices(c.State); len(down) > 0 {
|
||||
vals["service"] = strings.Join(down, ", ")
|
||||
}
|
||||
// {since} — only at hour scale. Below an hour the phrase would be minutes,
|
||||
// and none of the templates read well with "сорок минут".
|
||||
// and none of the templates read well with "сорок минут". service_down has
|
||||
// no {since} to offer: its facts are keyed by monitor, and the rule is
|
||||
// edge-triggered, so it fires on the transition rather than hours later.
|
||||
if d, ok := c.State.Since(rule); ok && d >= time.Hour {
|
||||
if s := ruSinceWords(d); s != "" {
|
||||
vals["since"] = s
|
||||
}
|
||||
}
|
||||
// {service} — the aggregate fact's key carries the service name.
|
||||
if f, ok := c.State.Fact(rule); ok && f.Key != "" && f.Key != rule {
|
||||
vals["service"] = f.Key
|
||||
}
|
||||
// {what} — the Russian suffix of "routine:таблетки" / "morning:утро".
|
||||
if i := strings.IndexByte(rule, ':'); i > 0 && i+1 < len(rule) {
|
||||
vals["what"] = rule[i+1:]
|
||||
|
||||
Reference in New Issue
Block a user