From 126ac75a25fcec029cbb68f9a844d8610e62f8f0 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Fri, 19 Jun 2026 22:10:55 -0400 Subject: [PATCH] fix(webtorrent): stop feed health-probe connection storm (freeze/crash) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The feed's per-card stream-health badges ran WebTorrent swarm probes at PROBE_CONCURRENCY = 96, and each probe's torrent.add set no maxConns (WebTorrent default 55 peers). Loading/scrolling the feed could therefore open ~96 x 55 simultaneous WebSocket/WebRTC connections, pegging the main thread (freeze) and exhausting memory (tab crash); playing a video added the streaming torrent on top and tipped it over. This also produced the MaxListenersExceeded warnings and relay/connection storms. - gridHealth: PROBE_CONCURRENCY 96 -> 4 (probes are real swarm joins, not pings). - webtorrent probePeers add: maxConns: 4 (a probe only needs to see >=1 peer). - webtorrent playback add: maxConns: 30 (caps the streaming handshake storm; ample for playback bandwidth). Pre-existing issue (not from the file-size refactor — verified). Confirmed locally: feed scroll + playback no longer freeze/crash. grid-health + webtorrent-regression tests pass; build green. Co-Authored-By: Claude Opus 4.8 --- js/gridHealth.js | 7 ++++++- js/webtorrent.js | 10 +++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/js/gridHealth.js b/js/gridHealth.js index f5bedf8e..8b67c7de 100644 --- a/js/gridHealth.js +++ b/js/gridHealth.js @@ -230,7 +230,12 @@ function queueProbe(magnet, cacheKey, priority = 0, webSeeds = []) { const PROBE_CACHE_TTL_MS = FIVE_MINUTES_MS; const PROBE_TIMEOUT_MS = 20000; -const PROBE_CONCURRENCY = 96; +// Each probe is a real WebTorrent swarm join (tracker announces + peer +// connections), NOT a cheap ping. At 96 concurrent, loading/scrolling the feed +// opened hundreds-to-thousands of simultaneous WebSocket/WebRTC connections, +// pegging the main thread and exhausting memory (freeze + tab crash). Keep this +// small — badges still populate, just a few at a time. +const PROBE_CONCURRENCY = 4; const PROBE_POLL_COUNT = 3; class ProbeQueue { diff --git a/js/webtorrent.js b/js/webtorrent.js index 392ae523..5c9f85b1 100644 --- a/js/webtorrent.js +++ b/js/webtorrent.js @@ -184,6 +184,11 @@ export class TorrentClient { const addOptions = { announce: trackers, maxWebConns: safeMaxWebConns, + // A probe only needs to detect that >=1 peer/webseed exists, so cap + // peer connections hard. Without this WebTorrent defaults to 55 per + // torrent — multiplied across concurrent probes that floods the + // browser with connections (freeze/crash). + maxConns: 4, }; /** * CRITICAL: We pass the webseed URL (if present) to the client via `urlList`. @@ -933,7 +938,10 @@ export class TorrentClient { .filter((entry) => /^https?:\/\//i.test(entry)) : []; - const chromeOptions = { strategy: "sequential" }; + // Cap peer connections for the streaming torrent too. 30 is plenty to + // saturate playback bandwidth while avoiding the WebRTC-handshake storm + // that can peg the main thread (WebTorrent's default is 55). + const chromeOptions = { strategy: "sequential", maxConns: 30 }; /** * CRITICAL: Passing `urlList` ensures the client can stream from the webseed. * Without this, videos with 0 P2P peers will fail to play even if a valid