When a peer reconnects while its previous sync stream is still parked
server-side (the old socket died without a FIN, e.g. on a mobile network
switch), CreateChannel replaces the old update channel and wakes the old
handler, whose teardown then closed the replacement channel, cancelled the
new session's TURN/relay token refresh and re-scheduled ephemeral cleanup
for a live peer. The client saw its fresh sync stream end with EOF and
bounced through Connecting right after reconnecting.
Teardown is now fenced by channel ownership, mirroring the session fencing
already used for the peer status DB writes and the signal server registry:
a session only closes the channel it registered, and when a newer session
owns the peer the whole teardown is skipped. The job stream close is fenced
the same way so a stale handler no longer fails the pending jobs served by
the new stream. Explicit closes (peer delete, DisconnectPeers) keep running
the full cleanup.
* Add gRPC update debouncing mechanism
Implements backpressure handling for peer network map updates to
efficiently handle rapid changes. First update is sent immediately,
subsequent rapid updates are coalesced, ensuring only the latest
update is sent after a 1-second quiet period.
* Enhance unit test to verify peer count synchronization with debouncing and timeout handling
* Debounce based on type
* Refactor test to validate timer restart after pending update dispatch
* Simplify timer reset for Go 1.23+ automatic channel draining
Remove manual channel drain in resetTimer() since Go 1.23+ automatically
drains the timer channel when Stop() returns false, making the
select-case pattern unnecessary.