fix(websocket): add server-side heartbeat to prevent proxy idle disconnects#770
fix(websocket): add server-side heartbeat to prevent proxy idle disconnects#770cvrysanek wants to merge 1 commit into
Conversation
…isconnects The WebSocket gateway never sent ping frames, so any reverse proxy with an idle timeout (Cloudflare Tunnel ~100s, AWS ALB 60s, nginx 60s, etc.) would silently tear down /shell, /ws and /plugin-ws/* connections after the idle window. The UI reconnects automatically but users see a "Connecting to shell" toast every 1–3 minutes during normal use and any in-flight PTY/chat traffic can race the reconnect. Schedule a 30s ws.ping() per connection at the gateway level, cleared on close/error. ping/pong counts as protocol activity for all proxies that implement WebSocket correctly, so this single change covers every deployment topology without per-proxy tuning. Fixes siteboon#769
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR adds an application-level WebSocket heartbeat to the gateway connection handler. Each new connection now starts a 30-second ping interval that keeps the socket alive across reverse-proxy idle timeouts, clears the interval on close/error, and uses try/catch to tolerate concurrent socket closure failures. ChangesWebSocket Heartbeat
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
ws.ping()heartbeat per WebSocket connection increateWebSocketServer, cleared onclose/error.Why
The
wslibrary does not heartbeat by default — it's an opt-in pattern documented in the ws README. Without app-level pings, an idle WebSocket has no protocol traffic and is reaped by the first reverse proxy in the path. CloudCLI users behind Cloudflare Tunnel see this constantly:/shell,/ws, and/plugin-ws/*all flap. Issue #769 has the full server-log trace from a live instance.What changed
server/modules/websocket/services/websocket-server.service.ts— one block added inside the existingwss.on('connection', ...)handler, before the route dispatch:Placed at the gateway so every route (
/shell,/ws,/plugin-ws/*) is covered without touching individual handlers.Why 30s
wsREADME example.Risk / compatibility
close/errorsemantics preserved; heartbeat cleanup is purely defensive.What was validated locally
The equivalent patch was hot-applied to the compiled
dist-serverJS on a running CloudCLI 1.32.0 instance behind Cloudflare Tunnel (the same instance whose logs are in #769):cloudcli.servicereportsactive (running);:3001listening.websocket-server.service.js; web-terminal plugin came up cleanly.I have not measured idle-duration behavior over a long window yet — would appreciate maintainer review or CI runs to confirm reconnect frequency drops on a known-bad proxy environment before merge.
Test plan
Summary by CodeRabbit