Files
mc-webui/requirements.txt
T
MarekWo fd054a95bd perf: let the realtime socket upgrade to a WebSocket
Three tabs open made every endpoint answer in ~20s, which two sessions read as
contention on a shared server-side lock. It wasn't the server. With 3 tabs open,
/health - which touches neither the database nor the device - measured a 14.7s
median from inside a tab and 11ms from a client outside the browser at the same
instant. The server was idle throughout.

Socket.IO clients pinned transports: ['polling'], upgrade: false, so each tab
held one HTTP connection open for its whole lifetime. Browsers allow six
concurrent HTTP/1.1 connections per origin, shared across every tab, so three
tabs consumed the pool and everything else queued in the browser waiting for a
free connection. /proc/net/tcp in the container confirmed it: pinned at exactly
6 established connections, unmoving.

The pin dates from 1d47c9c, when werkzeug had no WebSocket support and every
upgrade attempt returned HTTP 500. python-engineio==4.8.1 (pinned five weeks
later, in d3590f9) pulls in simple-websocket, which fixed that; the workaround
had outlived its premise. Drop it and use the default transports, which open on
polling and upgrade. A WebSocket is not part of the HTTP pool, so the pool is
released. Where the upgrade is blocked - a proxy that drops the Upgrade header -
the client stays on polling by itself, which is exactly today's behaviour.

Measured with 3 tabs, in-page medians: /health 14664ms -> 12ms, /api/status
19282ms -> 64ms, both now matching what the same probes read from outside the
browser. All three tabs report transport "websocket", server pushes still
arrive over it, and the log no longer fills with "Session is disconnected"
(0 occurrences, 0 tracebacks across the run).

Also corrects the earlier diagnosis in the docs: the per-endpoint timings that
looked like a lock were measured request->requestfinished in the browser, which
includes connection-queue time, so every endpoint flattened to the same figure
regardless of its own cost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 09:31:40 +02:00

42 lines
980 B
Plaintext

# mc-webui Python Dependencies
# Web Framework
Flask==3.0.0
Werkzeug==3.0.1
# WSGI Server for production
gunicorn==21.2.0
# Configuration
python-dotenv==1.0.0
# Scheduled Tasks
APScheduler==3.10.4
# Date/Time Utilities
python-dateutil==2.8.2
# QR Code Generation
qrcode==7.4.2
Pillow==10.1.0
# HTTP Client for MeshCore Bridge communication
requests==2.31.0
# Cryptography for pkt_payload computation (AES-128-ECB)
pycryptodome==3.21.0
# WebSocket support for console (threading mode - no gevent needed)
flask-socketio==5.3.6
# Observer: MQTT packet publishing (meshcore-packet-capture compatible)
paho-mqtt==2.1.0
python-socketio==5.10.0
# Pulls in simple-websocket, which is what lets the werkzeug server serve real
# WebSockets. Clients rely on that upgrade; without it they fall back to
# long-polling and starve the browser's per-origin connection pool.
python-engineio==4.8.1
# v2: Direct MeshCore device communication (replaces bridge subprocess)
meshcore>=2.3.7