onPeerRecovered

abstract fun onPeerRecovered(peerId: PeerId, at: Long)

peerId became responsive again without resuming — close its reconnect window, and close it without expiring it.

The counterpart of onPeerUnresponsive on the lane that has no token in it. A peer whose link merely blipped is restored by the liveness detector alone: it never presents a ResumeToken, so tryResume — the only other thing that closes a window — is never reached, and before this method existed the window a blip opened stayed armed for its full duration behind a peer that was already back (#2556). What that stale timer then does is not cosmetic: its JoinerReconnectEvent.WindowExpired is what a room fans out as an authoritative farewell, so a healthy member was evicted from every roster but the host's.

The obligation: emit no JoinerReconnectEvent.WindowExpired for the episode this closes. That is the whole contract — an implementation with no timer to cancel (a hold policy that only ever answers questions) satisfies it by doing nothing, and should say so rather than leave a reader guessing. at identifies the recovery instant for logging; it is not an expiry, so do not treat it as one.

Distinct from expire, deliberately, and not expressible in terms of it: expire is an expiry — it emits JoinerReconnectEvent.WindowExpired and leaves the window terminally closed, so a later tryResume answers ResumeResult.WindowClosed ("re-join fresh") where the honest answer for a recovered peer is that no window is pending at all. Routing recovery through it would re-file a blip as a kick.

Idempotent, and a no-op for a peer with no open window.