Skip to content

feat: Parallel setup, WebSocket I/O, per-session locks - #47

Closed
dgokeeffe wants to merge 1 commit into
datasciencemonkey:mainfrom
dgokeeffe:feat/performance-improvements
Closed

dgokeeffe wants to merge 1 commit into
datasciencemonkey:mainfrom
dgokeeffe:feat/performance-improvements

Conversation

@dgokeeffe

Copy link
Copy Markdown
Contributor

Summary

Three performance improvements for the terminal app:

  • Parallel setup: Agent setup scripts (claude, codex, opencode, gemini, databricks, mlflow) run concurrently via ThreadPoolExecutor after sequential git+micro prerequisites. Cuts startup time ~5x.
  • WebSocket terminal I/O: Flask-SocketIO pushes PTY output in real-time via Socket.IO with automatic HTTP polling fallback. Includes auth on connect, join/leave room lifecycle, and session exit/close notifications.
  • Per-session locks: Each session gets its own threading.Lock() — global lock only guards dict-level add/remove/iterate. Atomic buffer swap in get_output() reduces contention when running multiple terminals.

Changes

  • app.py — All three features integrated (parallel setup, SocketIO handlers, _get_session() + per-session lock pattern)
  • gunicorn.conf.py — Timeout 30→120s for long-lived WebSocket connections
  • requirements.txt — Added flask-socketio>=5.3, simple-websocket>=1.0
  • static/index.html — Socket.IO client with WebSocket-first transport + HTTP polling fallback
  • docs/prd/websocket-terminal-io.md — PRD for WebSocket feature

Test plan

  • Verify app starts and setup completes (parallel setup)
  • Open terminal, confirm real-time output via WebSocket (check browser console for [ws] Connected)
  • Open multiple terminals simultaneously, confirm no lag or contention
  • Kill WebSocket (e.g. network drop) — confirm HTTP polling fallback kicks in
  • Verify auth still enforced (unauthorized user gets rejected on both HTTP and WS)

🤖 Generated with Claude Code

Three performance improvements integrated:

1. Parallel setup: Agent setup scripts (claude, codex, opencode, gemini,
   databricks, mlflow) run concurrently via ThreadPoolExecutor after the
   sequential git+micro prerequisites. Cuts startup time ~5x.

2. WebSocket terminal I/O: Flask-SocketIO pushes PTY output in real-time
   via Socket.IO with automatic HTTP polling fallback. Adds join/leave
   room lifecycle, auth on connect, and session exit/close notifications.

3. Per-session locks: Replace global sessions_lock with per-session Lock
   for buffer access. Global lock only guards dict-level add/remove/iterate.
   Atomic buffer swap in get_output() reduces lock contention.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
datasciencemonkey added a commit that referenced this pull request Mar 9, 2026
Apply PR #47 from David O'Keeffe with the following enhancements:
- Parallel setup via ThreadPoolExecutor (~5x faster startup)
- Per-session locks (reduced contention vs global lock)
- WebSocket terminal I/O via Flask-SocketIO (eliminates 50-200ms polling latency)

Fixes applied on top of PR #47:
- Fix session timeout: update last_poll_time on WS output emit
- Vendor Socket.IO client to /static/lib/ (avoid CDN dependency)
- Restrict CORS: cors_allowed_origins=[] (same-origin only)
- Increase thread pool: 8→16 for WS connection headroom
- Adjust gunicorn timeout: 120s→60s (balanced for WS + hung-worker detection)
- Clear output buffer on WS join (prevent duplicate output on transport switch)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@datasciencemonkey

datasciencemonkey commented Mar 9, 2026 •

Copy link
Copy Markdown
Owner

Excellent stuff! Resolving a few merge conflict and closing out quick and dirty fixes here #48 (comment)

@datasciencemonkey

Copy link
Copy Markdown
Owner

Closing this, #48 builds on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants