diff --git a/modules/messenger/cmd/messenger/holder.go b/modules/messenger/cmd/messenger/holder.go index a2dcfaf3..120daa75 100644 --- a/modules/messenger/cmd/messenger/holder.go +++ b/modules/messenger/cmd/messenger/holder.go @@ -1130,6 +1130,8 @@ func (h *Holder) record(s Sent) { if h.Store != nil { if err := h.Store.PutRecent(recent); err != nil { h.noteStore(err) + } else { + h.storeWritten() } } } @@ -1143,6 +1145,20 @@ func (h *Holder) persist(r *Record) { h.mu.Unlock() if err := h.Store.Put(c); err != nil { h.noteStore(err) + } else { + h.storeWritten() + } +} + +// storeWritten clears a state problem once a write succeeds again: the status says what holds now, never a +// failure that passed (issue 1507's reading of 2026-10-28: a verdict kept a single failure of the day before). +func (h *Holder) storeWritten() { + h.mu.Lock() + was := h.storeErr + h.storeErr = "" + h.mu.Unlock() + if was != "" { + h.Logf("[messenger] writes its state again (it could not: %s)", was) } } diff --git a/modules/messenger/cmd/messenger/holder_test.go b/modules/messenger/cmd/messenger/holder_test.go index 980721c3..056e8354 100644 --- a/modules/messenger/cmd/messenger/holder_test.go +++ b/modules/messenger/cmd/messenger/holder_test.go @@ -71,9 +71,14 @@ type memStore struct { passes map[string]Pass // puts counts the writes, so a write of bytes identical to what is stored is still seen (issue 422's review). puts int + // fail, when set, refuses every write of a record or of the sends, as the bus does with no responders. + fail error } func (m *memStore) Put(r Record) error { + if m.fail != nil { + return m.fail + } if m.recs == nil { m.recs = map[string]Record{} } @@ -89,7 +94,13 @@ func (m *memStore) All() ([]Record, error) { } return out, nil } -func (m *memStore) PutRecent(s []Sent) error { m.recent = s; return nil } +func (m *memStore) PutRecent(s []Sent) error { + if m.fail != nil { + return m.fail + } + m.recent = s + return nil +} func (m *memStore) PutWalk(w Walk) error { if m.walks == nil { m.walks = map[string]Walk{} @@ -431,15 +442,21 @@ func TestEscalationIsSaidOnce(t *testing.T) { } func TestAChannelThatCannotSendSaysSoAndIsTriedAgain(t *testing.T) { - h, tg, _, c, _ := newHolder(t) + h, tg, _, c, store := newHolder(t) h.Desk = nil tg.fail = errors.New("telegram sendMessage: cannot connect (dial)") + // The state could not be written either, once: said while it lasts, and no longer once a write succeeds + // (issue 1507's reading of 2026-10-28: a verdict kept a day-old "no responders"). + store.fail = errors.New("nats: no responders available for request") h.Condition(EventRaised, cond("machine.ace.silent", Urgent, "silent")) st := h.Status("listening") if !strings.HasPrefix(st.Verdict, "CANNOT SEND") || len(st.Unsent) != 1 || st.Channels[0].LastError == "" { t.Fatalf("status: %+v", st) } - tg.fail = nil + if st.StateProblem == "" { + t.Fatalf("a failed state write is not said: %+v", st) + } + tg.fail, store.fail = nil, nil h.Flush() if len(tg.sends) != 0 { t.Fatalf("tried again before a minute")