Files
pad/cmd
xarmian 8dea9abca3 feat(watchevents,metrics): operational observability for the Redis notification bus (BUG-2727)
The watch bus detects four conditions an operator would want to alert on —
a notification dropped for a slow local subscriber, a gap in the received
id sequence, an id-space reset, and the receive loop stopping — and until
now reported all four to slog and nowhere else. Log lines are not
alertable without someone already looking, and the last of the four was
not even logged: the loop returned silently, leaving an instance that
publishes fine and receives nothing indistinguishable from a quiet
workspace.

Adds watchevents.Observer, an adapter seam rather than a bus wrapper.
The events.EventBus wrapper shape does not work here: every condition is
detected on the RECEIVE path, inside the bus, and is invisible at the Bus
interface — a wrapper can count publishes and subscribers, but not a
notification that never arrived.

Two corrections to BUG-2727's filing, both verified against go-redis
v9.22.0 rather than assumed:

- Its proposed fix — "re-subscribe rather than exiting where the cause is
  recoverable" — would be dead code. PubSub.Channel's message channel is
  closed ONLY on pool.ErrClosed; every other receive error is retried
  indefinitely, and a health-check goroutine pings every 3s and
  reconnects on failure. So go-redis already does the re-subscribing. The
  exit gets an ERROR log and a counter instead, which is what the
  condition actually needs.
- The genuinely silent path is go-redis DROPPING messages when a
  subscription's 100-deep buffer stays full past its 60s send timeout,
  logged only through go-redis's own logger. Pad cannot count that
  directly, so it is reported by its CONSEQUENCE (a sequence gap) and its
  cause is made visible by routing go-redis's logger into slog.
  Observer's doc comment states that boundary, so a gap is not misread as
  evidence of any particular cause.

Session presence gets the same treatment for the same reason: it is
fail-soft everywhere by design, so its failures have no user-visible
signal beyond a push that quietly reaches fewer sessions than it should.
The renew counter is deliberately NOT throttled where its log line is —
throttling the metric would make it under-report during the incident it
exists for.

Tests assert the CONDITION increments the counter, not that the counter
exists, and each asserts its own premise first (a healthy subscriber
reports nothing; contiguous ids report nothing; a cold start reports
nothing) so a bus that reported on every notification could not pass. The
receive-loop test drives the real closed-client condition rather than
calling the reporter.

Claude-Session: https://claude.ai/code/session_01JVDBKbgn3Xt7ndW1YoYd8X
2026-08-22 01:21:50 +00:00
..