Overview We are observing recurring WebSocket disconnections in XWiki (Netflux) when the browser tab has been in the background for more than 5 minutes. This interrupts collaborative editing sessions. Root Cause Analysis: Modern versions of Google Chrome enable "IntensiveWakeUpThrottlingEnabled" by default. This feature throttles Javascript timers (setTimeout / setInterval) in background tabs (hidden for >5 minutes) to run only once per minute (60 seconds). In netflux-client.js, the keep-alive logic is defined as follows:
var MAX_LAG_BEFORE_PING = 15000;
var MAX_LAG_BEFORE_DISCONNECT = 60000;
ctx.pingInterval = setInterval(function () {
if (now() - ctx.timeOfLastPingReceived < MAX_LAG_BEFORE_PING) { return; }
if (now() - ctx.timeOfLastMsgReceived > MAX_LAG_BEFORE_DISCONNECT) {
closeWebsocket(ctx);
}
}, PING_CYCLE);
The Race Condition Chrome throttles the setInterval execution to exactly 60,000ms (1 minute). The code checks if the last message was received more than MAX_LAG_BEFORE_DISCONNECT (60,000ms) ago. Because the throttled interval fires slightly after 60s (e.g., at 60,005ms or due to slight execution delays), the condition diff > 60000 evaluates to true. The WebSocket is closed immediately, even though the connection might still be valid. Evidence Below is a screenshot from the Chrome Developer Tools showing the WebSocket traffic. You can see the Pings occur normally at first, but once throttling kicks in, the interval stretches to ~60s, leading to the disconnect.  Steps to Reproduce Open an XWiki document with Realtime editing enabled in Chrome. Open a new tab and focus it (leaving the XWiki tab in the background). Wait for at least 5 minutes (triggering Chrome's intensive throttling). Observe that the WebSocket connection drops shortly after. Proposed Solution To accommodate browser throttling policies, the disconnect threshold should be higher than the browser's minimum throttle interval (60s). I suggest increasing MAX_LAG_BEFORE_DISCONNECT to 80,000 (80 seconds) or higher. This provides a safety buffer for the throttled interval to execute and send a ping before the disconnect logic triggers.
var MAX_LAG_BEFORE_DISCONNECT = 80000;
|