Agent 2.16.0 — Throttle del resync histórico + diagnóstico del flapping WS + aviso de portátil
Resumen
La versión 2.16.0 del Local Agent resuelve un bucle vicioso de amplificación de datos: cuando la conexión WebSocket con el servidor se vuelve inestable (flapping), el Agente re-enviaba las 24 horas completas de métricas en CADA reconexión, lo que a su vez sobrecargaba la red y tumba la conexión nuevamente (22× de amplificación documentada en YogaEdu, 21-07-2026). Esta release implementa:
- Throttle del backfill histórico (#203): solo se re-arma tras un corte real (≥10 min) y solo el hueco faltante, no 24h.
- Instrumentación del cierre WS (#203): los
close_codey la duración de cada sesión se loguean y exponen en/info(antes invisible). - Aviso de portátil desde el día 1 (#197): el Agente reporta si vive en una máquina con batería (
psutil.sensors_battery) → el aviso del Sentinel 24/7 salta inmediatamente. - Bump de seguridad:
websockets15.0.1 → 16.1.1 en el lock (solo instalaciones frescas).
Problema diagnosticado (22-07-2026, en vivo)
Síntomas observados
- Flapping del WS: YogaEdu, ~3.539 reconexiones el 21-07, duración por sesión ~6,6s.
- Círculo vicioso: cada reconexión armaba un
push_historical(24h)de 5.000 métricas (~33-39s por batch) → la conexión solo duraba 6,6s → resync sin fin. - Amplificación: el bombardeo de datos ayudaba a tumbar la propia conexión (causa probable: saturación uplink + event loop/storage).
- Punto ciego de observabilidad: el
close_codey las stats de reconexión no se exponían en ninguna ruta.
Datos de diagnostico
- Agente:
agent_ca6ba7b2364f(Edu, YogaEdu, v2.15.1 onedir, 131 targets, metrics.db 197 MB). - Correlación server-side: cada
WSDISCONNECTllegaba justo tras un bulk POST de 1000 métricas. - Query:
SELECT COUNT(*) FROM agent_log WHERE created_at > '2026-07-21' AND level='WSRECONNECT'→ 3.539 en 24h (único incident en la flota).
Cambios técnicos
#203 · Throttle del resync + Instrumentación
terminal/agent/core/sync.py:
- Registra
_disconnected_atenon_disconnected(). - En reconexión, distingue:
- Downtime < 10 min (criterio
DISCONNECT_GAP_MINUTES = 600): NO resync histórico. El flujo normal (push_unsynced()) cubre las filas pendientes. - Downtime ≥ 10 min: resync SOLO del hueco real =
(downtime + margen 15 min, cap 24h). - Cooldown 15 min: mínimo tiempo entre resyncs completados.
- Downtime < 10 min (criterio
- Primer backfill tras arranque sigue siendo completo (alimenta Observatory/gráficas).
- Guard server-side v1.61.2 actúa como segunda línea de defensa.
terminal/agent/core/connector.py:
- Loguea
close_code, motivo y duración al salir del receive loop. - Expone stats en
/infosecciónsaas.ws:reconnect_count: contador global desde arranque.last_close_code: código HTTP/WS del último cierre.last_session_secs: segundos de la última sesión.last_error: string del último error registrado (si aplica).
#197 · Aviso de portátil
terminal/agent/core/agent_status.py:
- Agrega campo
has_battery=psutil.sensors_battery()(psutil ya empaquetado desde v2.13.2). - Registra en BD: migración
terminal_0005añadeAgentInstance.has_battery(NULL para agents viejos). - Consumidor SaaS la persiste en
agent_status.
static/js/pages/observatory/ObservatorySentinel.js:
- En
_primaryStabilityWarning(), siprimary.has_battery === true, salta el aviso de portátil desde el día 1 (antes solo saltaba tras ≥3 cortes largos en 7 días, v1.49.0). - i18n ES incluida en
djangojs.po.
#196 · Bump websockets
terminal/agent/requirements-agent.lock:websockets 15.0.1→16.1.1.- Sin CVE. Límite honesto: flota existente se actualiza por paquete de código, NO recibe la lib (queda en 15, sin riesgo). Solo instalaciones frescas del
Setup.exellevan 16.
Verificación post-deploy
- KPI resync: reconexiones/h en YogaEdu deben caer a ~0 (normal background reconexiones por red office/VPN).
- close_code logs: si WS sigue cayendo, los logs dirán quién corta (Cloudflare / Daphne / red).
- Batería: portal Sentinel detecta portátiles desde activation day 1.
Releases
- Agent: v2.16.0 (bump
terminal/agent/version.py). - SaaS: v1.62.0 (migración terminal_0005, campos model
has_battery, i18n).
Tasks asociadas
- #203: Throttle del resync + instrumentación WS → merged 22-07-2026 11:04 UTC.
- #196: Bump websockets → merged 22-07-2026 11:04 UTC.
- #197: has_battery + aviso portátil → merged 22-07-2026 11:04 UTC.
Véase también
- [[entity—terminal—service—sync-throttle]]
- [[entity—terminal—service—connector-ws-diagnostics]]
- [[entity—terminal—model—agent-instance]]
- [[concept—infra—agent-health-monitoring]]
- [[concept—saas—high-availability]]