Skip to content

Make the runtime observable for operators (O-8) - #29

Open
windischb wants to merge 1 commit into
developfrom
feat/block7-operator-visibility
Open

Make the runtime observable for operators (O-8)#29
windischb wants to merge 1 commit into
developfrom
feat/block7-operator-visibility

Conversation

@windischb

Copy link
Copy Markdown
Collaborator

Summary

Block 7, PR 4 of the agreed slicing — finding O-8 from the 2026-08 review. Completes the O-block.

  • Stream bookkeeping is countable: ServerStreamManager.ActiveStreamCount, pending download/upload-slot counts, and instruments signalarrr.server.active_streams / .streams.reaped / .upload_slots.swept. Leaked streams used to be unmeasurable and invisible.
  • Idle-stream reaper: streams that were created but never consumed are reaped after StreamIdleTimeout (default 10 min, WithStreamIdleTimeout); their producer gets a completing error instead of writing into the void. Streams with a reader attached are never touched — their lifecycle ends via the read loop''s finally or the disconnect cleanup.
  • Backplane health surface: GetActiveNodesAsync() (self + live remotes), last successful heartbeat, heartbeat-loop-faulted, and a Redis PING.
  • services.AddSignalARRRHealthChecks(): standard IHealthCheck (name signalarrr). Verdicts an operator can act on: heartbeat loop dead or store unreachable → Unhealthy; heartbeat stale beyond two intervals → Degraded (the warning before the cluster declares the node dead and wipes its registrations — the V-3 scenario); node list and counts in the health data. Without a backplane: Healthy with the stream counts.

Verification

  • Unit: count lifecycle (consumed stream leaves nothing; disconnect clears per-connection), reaper semantics (never-consumed reaped + producer notified; actively-read stream never reaped), health verdicts for all four states (disabled / faulted / unreachable / stale / healthy-with-nodes) against a fake backplane.
  • Integration: /health endpoint on the real server returns Healthy.
  • Full suite green locally on all TFMs gate-style: 174 unit + 112 integration + 12 dynamic-proxy per TFM, plus net48 (19).

🤖 Generated with Claude Code

Both stream managers were private without a count - a leaked stream was
unmeasurable and invisible - and the backplane had no health surface: no node
list, no last-heartbeat, no way to notice the heartbeat loop had died before
the cluster declares the node dead and wipes its registrations.

ServerStreamManager now counts (ActiveStreamCount, signalarrr.server.
active_streams) and reaps streams that were created but never consumed
(StreamIdleTimeout, default 10 min; streams with a reader attached are never
touched - their lifecycle ends via the read loop or disconnect cleanup).
Upload-slot sweeps are counted too. The backplane exposes GetActiveNodesAsync
and a health surface (last successful heartbeat, loop-faulted, PING), and
services.AddSignalARRRHealthChecks() turns all of it into a standard health
check: heartbeat-loop dead or store unreachable -> Unhealthy, heartbeat stale
beyond two intervals -> Degraded before the cluster acts, node list in the
data.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant