From 7a31469d695416b9964961c779a7fc92baf36bbf Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 11 Apr 2026 15:14:37 +0200 Subject: [PATCH] fix(vitalsharing): don't evict subscribers on transient send failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _broadcast_share_to_plugin_clients was discarding a character from _vital_sharing_subscribers whenever a single send_json hit the 1-second timeout or raised any exception. Under heavy load this permanently dropped clients from the subscriber set even though their WebSocket was still fully connected — the user had to toggle vital sharing off and on to get peer updates flowing again. Now we log the send failure but leave the subscriber intact. Actual eviction still happens on real WebSocket disconnect via the finally block in the plugin receive loop. Co-Authored-By: Claude Opus 4.6 (1M context) --- main.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index bd428c6c..55b874a8 100644 --- a/main.py +++ b/main.py @@ -2419,10 +2419,16 @@ _vital_sharing_peer_state: Dict[str, dict] = {} async def _broadcast_share_to_plugin_clients(data: dict, origin: str) -> None: - """Forward a share_* message to all opted-in plugin clients except origin.""" + """Forward a share_* message to all opted-in plugin clients except origin. + + Transient send failures are logged but do NOT evict the subscriber — + eviction only happens on actual WebSocket disconnect (handled in the + plugin receive loop's finally block). Evicting aggressively here caused + a bug where a single slow send would silently drop a subscriber and + force the user to retoggle vital sharing to get peer updates again. + """ if not _vital_sharing_subscribers: return - stale: list[str] = [] for char_name, ws in list(plugin_conns.items()): if char_name == origin: continue @@ -2432,9 +2438,6 @@ async def _broadcast_share_to_plugin_clients(data: dict, origin: str) -> None: await asyncio.wait_for(ws.send_json(data), timeout=1.0) except Exception as e: logger.debug(f"Failed forwarding share_* to {char_name}: {e}") - stale.append(char_name) - for name in stale: - _vital_sharing_subscribers.discard(name) def _update_vital_sharing_peer_state(msg_type: str, data: dict) -> None: