CreaRack-SL

Servicio Sync-Throttle del Local Agent (terminal/agent/core/sync.py)

Propósito

El módulo sync.py del Local Agent gestiona la sincronización de métricas histórico/unsynced con el servidor SaaS. Desde v2.16.0, implementa un throttle inteligente del backfill histórico para evitar amplificación de datos en caso de reconexiones frecuentes.

Funciones principales

on_connected()

  • Llamada tras establecer la conexión WebSocket.
  • Evalúa si es necesario un resync histórico basándose en _disconnected_at.
  • Antes (v2.15.1): siempre llamaba push_historical(24h).
  • Desde v2.16.0: compara downtime con DISCONNECT_GAP_MINUTES (600 s = 10 min):
    • Si downtime < 10 min: solo push unsynced (flujo normal).
    • Si downtime ≥ 10 min: push histórico del hueco real (downtime + 15 min margen, cap 24h).
    • Respeta cooldown de 15 min entre resyncs completados.

push_unsynced()

  • Envía métricas pendientes (filas con synced=False) al servidor.
  • Operación de bajo costo (típicamente <100 métricas, <1 s).
  • Ejecutada en CADA reconexión breve (<10 min) en lugar del backfill completo.

push_historical(hours=24)

  • Consulta BD (metrics.db) por la ventana temporal especificada.
  • Agrupa en batches de ~1000 métricas (límite MAX_BATCH_PER_REQUEST).
  • Envía cada batch por POST al servidor.
  • Duración típica: 33-39 s por 5.000 métricas (5 batches × ~7s + ramp-up).
  • Punto de throttle: desde v2.16.0, solo se ejecuta si downtime ≥ 10 min.

on_disconnected()

  • Registra _disconnected_at = time.time() (timestamp UTC).
  • Permite a on_connected() calcular downtime en la próxima reconexión.
  • Novedad v2.16.0: integración con sleep-detection (si el agent entra en standby, _disconnected_at se fija correctamente).

Parámetros de configuración

ParámetroValorSignificado
DISCONNECT_GAP_MINUTES600 (10 min)Umbral para considerar un corte “largo”
MAX_BATCH_PER_REQUEST1000Máximo de métricas por POST al servidor
HISTORICAL_RESYNC_COOLDOWN_MIN15 (min)Mínimo de tiempo entre resyncs completados
HISTORICAL_RESYNC_CAP_HOURS24Techo máximo de ventana histórica a recuperar

Diagrama de estado

[CONECTADO]
    ↓ (on_disconnected)
[DESCONECTADO] → registra _disconnected_at
    ↓ (reconexión)
[VALIDANDO DOWNTIME]
    ├─ downtime < 10 min → push_unsynced() [bajo costo]
    └─ downtime ≥ 10 min → (cooldown expired?) 
         ├─ SÍ → push_historical(downtime + 15min) [caro, ~30-40s]
         └─ NO → push_unsynced() [bajo costo]
[CONECTADO]

Fuente de datos

  • Tabla metrics.db (SQLite en %APPDATA%/CreaRack/agent/metrics.db):

    • Schema: timestamp, target_id, metric_name, value, synced (bool).
    • Consultada por ventana temporal en push_historical(hours).
    • Actualizada por los collectors (SNMP, ping, HTTP) en tiempo real.
    • Marcada synced=True tras POST exitoso al servidor.
  • Servidor SaaS (/api/agent/metrics):

    • Endpoint que consume los POSTs.
    • Valida tenant, target_id, timestamps.
    • Persiste en monitoring.Metric (PostgreSQL).

Impacto v2.16.0

Problema resuelto

  • Antes: cada reconexión re-enviaba 24h completas (~5.000 métricas), independientemente de cuánto tiempo llevara fuera. Con WS flapeando (~6,6s de vida por conexión), entraba en loop infinito de resync.
  • Amplificación: 22× de overhead documentado (YogaEdu, 21-07-2026).
  • Síntomas: saturación de ancho de banda, CPU high, event loop bloqueado.

Solución implementada

  • Throttle basado en duración real del downtime.
  • Backfill solo del hueco faltante (no 24h completas).
  • Cooldown de 15 min entre resyncs para evitar resonancia.
  • Flujo unsynced sigue siendo completo (cubre micro-cortes <10 min).
  • Primer resync tras arranque es aún completo (alimenta Observatory).

Verificación post-deploy

  • KPI: reconexiones/h en YogaEdu deben caer a baseline (~0, solo background noise).
  • Si WS sigue cayendo → diagnostico en close_code logs (segunda línea: connector.py).

Tests

  • Test de throttle: test_sync_throttle_downtime_<10min (no resync).
  • Test de resync: test_sync_throttle_downtime_>=600s (resync del hueco).
  • Test de cooldown: test_sync_throttle_cooldown_15min (segundo resync bloqueado).
  • Coverage: 8 tests nuevos en v2.16.0, 106 tests agente en total (verdes en Docker).

Referencias de código

  • Archivo: terminal/agent/core/sync.py
  • Última actualización: 2026-07-22 11:04:33 UTC (commit 9679f97).
  • Función pública: class SyncManager(BaseModel) → on_connected(), on_disconnected(), push_unsynced(), push_historical().

Véase también

  • [[feature—agent—resync-throttle-v2160]]
  • [[entity—terminal—service—connector-ws-diagnostics]]
  • [[concept—infra—agent-health-monitoring]]
  • [[entity—terminal—model—metric]]
  • [[concept—performance—data-amplification-avoidance]]