diff --git a/static/index.html b/static/index.html
index ac87db1..0df0b68 100644
--- a/static/index.html
+++ b/static/index.html
@@ -893,21 +893,52 @@
General
socket = io({ transports: ['websocket', 'polling'] });
socket.on('connect', () => {
- console.log('[ws] Connected');
- wsConnected = true;
- // Re-join rooms for all active panes and stop their HTTP polling (AC-16)
+ // Check actual transport — Socket.IO reports connected=true even on long-polling
+ // through Databricks proxy. Only stop poll-worker for true WebSocket.
+ const transport = socket.io.engine.transport.name;
+ const isTrueWS = transport === 'websocket';
+ console.log(`[ws] Connected (transport: ${transport}, trueWS: ${isTrueWS})`);
+
+ // Always join rooms regardless of transport
getAllPanes().forEach(p => {
if (p.sessionId) {
socket.emit('join_session', { session_id: p.sessionId });
- pollWorker.postMessage({ type: 'stop_poll', paneId: p.id });
}
});
- // Start WS heartbeat — keeps idle sessions alive (replaces poll-worker keepalive)
- if (wsHeartbeatTimer) clearInterval(wsHeartbeatTimer);
- wsHeartbeatTimer = setInterval(() => {
- const sids = getAllPanes().map(p => p.sessionId).filter(Boolean);
- if (sids.length > 0) socket.emit('heartbeat', { session_ids: sids });
- }, WS_HEARTBEAT_INTERVAL);
+
+ if (isTrueWS) {
+ wsConnected = true;
+ // Only stop poll-worker when we have a real WebSocket
+ getAllPanes().forEach(p => {
+ if (p.id) pollWorker.postMessage({ type: 'stop_poll', paneId: p.id });
+ });
+ // Start WS heartbeat — keeps idle sessions alive (replaces poll-worker keepalive)
+ if (wsHeartbeatTimer) clearInterval(wsHeartbeatTimer);
+ wsHeartbeatTimer = setInterval(() => {
+ const sids = getAllPanes().map(p => p.sessionId).filter(Boolean);
+ if (sids.length > 0) socket.emit('heartbeat', { session_ids: sids });
+ }, WS_HEARTBEAT_INTERVAL);
+ } else {
+ console.log('[ws] Connected via polling — keeping poll-worker active');
+ // Don't set wsConnected — poll-worker stays active as primary transport
+ }
+
+ // Listen for late upgrade from polling → websocket
+ socket.io.engine.on('upgrade', (transport) => {
+ console.log(`[ws] Transport upgraded to: ${transport.name}`);
+ if (transport.name === 'websocket') {
+ wsConnected = true;
+ getAllPanes().forEach(p => {
+ if (p.id) pollWorker.postMessage({ type: 'stop_poll', paneId: p.id });
+ });
+ if (!wsHeartbeatTimer) {
+ wsHeartbeatTimer = setInterval(() => {
+ const sids = getAllPanes().map(p => p.sessionId).filter(Boolean);
+ if (sids.length > 0) socket.emit('heartbeat', { session_ids: sids });
+ }, WS_HEARTBEAT_INTERVAL);
+ }
+ }
+ });
});
socket.on('disconnect', (reason) => {