Status(GetFullPeerStatus=true) RPCs trigger a full health probe
(network round-trips to management, signal and the relays). The
desktop UI issues these frequently and concurrently, and a burst of
parallel Get() calls each fired its own probe — the lastProbe guard
was unprotected against concurrent access and only advanced when every
component was healthy, so a sustained unhealthy state (e.g. relay down)
disabled the throttle entirely and let every call re-probe.
Extract the throttle/single-flight policy into probeThrottle:
- single-flight: only one probe runs at a time; concurrent callers
that piled up while it ran share its result instead of each
launching another, even when that probe failed.
- throttle: lastOK only advances on a fully successful probe, so
while anything is unhealthy callers keep probing frequently and
notice recovery quickly (preserved from the original design).
RunHealthProbes now takes a context so a caller that gives up (e.g. a
Status RPC whose client disconnected) cancels the in-flight STUN/TURN
probe instead of letting it run to its per-component timeout. The
engine's own lifetime ctx still applies independently.
Adds a SubscribeStatus gRPC RPC that pushes a fresh FullStatus snapshot
on every peer-recorder state change, replacing the Wails UI's 2-second
Status poll. The daemon's notifier already triggers on Connected /
Disconnected / Connecting / management or signal flip / address
change / peers-list change; we now coalesce those into ticks on a
buffered chan and stream the resulting snapshots over gRPC.
- Status recorder gains SubscribeToStateChanges /
UnsubscribeFromStateChanges + a non-blocking notifyStateChange that
drops ticks when a subscriber's 1-slot buffer is full (next snapshot
the consumer pulls already reflects everything).
- Server.Status handler split: the snapshot composition is shared
with the new SubscribeStatus stream handler so unary and stream
paths return identical bytes.
- UI peers service: pollLoop replaced by statusStreamLoop. The local
name of the existing SubscribeEvents loop is now toastStreamLoop so
the two streams are easy to tell apart — the underlying RPC name is
unchanged.
- Tray applyStatus skips the icon refresh when connected/lastStatus
hasn't changed; rapid SubscribeStatus bursts during health probes
no longer churn Shell_NotifyIcon or the log.