InfraGuard

Actualizaciones en vivo (Reverb + sondeo)

Las dos formas en que las pantallas se refrescan solas — envíos instantáneos por WebSocket de Reverb y un sondeo ligero cada 30 segundos con un token de cambio rev muy barato — y por qué la consola nunca se rompe cuando los WebSockets están apagados.

Resumen — qué hace

Los paneles de InfraGuard se actualizan solos sin recargar la página. Esa actualización automática se apoya en dos mecanismos.

Mecanismo Cómo Latencia Lo usan
WebSocket de Reverb Servidor → navegador, envío instantáneo (dirigido por eventos) milisegundos trabajos en vivo que transmiten el progreso como ticks
Sondeo ligero El navegador hace GET a /…/live a intervalos hasta 30 s casi todos los paneles (Estado, Servidores, Tráfico, Servicio, Seguridad, Alertas …)

Una regla de diseño lo resume todo:

Lo «en vivo» es una mejora que se superpone a los datos persistidos. Cada pantalla renderiza primero los datos guardados en la base de datos, y las actualizaciones en tiempo real van encima. Por eso, aunque Reverb (el servidor WebSocket) esté apagado, bloqueado por un cortafuegos o reiniciándose, la pantalla nunca se rompe. Cuando el envío no está disponible, el sondeo cubre el hueco (degradación elegante).

En la práctica, casi todas las pantallas funcionan con sondeo. El WebSocket de Reverb está instalado y cableado, y hoy alimenta exactamente una función: la emulación remota del diagnóstico de seguridad (Emulación remota · Diagnóstico de seguridad), donde transmite ticks de progreso por host. Todas las demás pantallas en vivo se refrescan con un sondeo de 30 segundos más un token barato de detección de cambios, rev.


Cuándo usarlo

Esta es una referencia conceptual. No es una pantalla con ruta en vivo: está pensada para operadores e ingenieros que quieren entender:


Disposición

Arquitectura de dos caminos

[datos persistidos]  server_status · infr_db_metric · blacklist_info · …
      │
      ▼ (carga inicial de la página: el servidor inyecta JSON data-* en la vista)
[pantalla del navegador]  ← se renderiza al instante (completa sin nada en vivo)
      ▲                          ▲
      │ (A) sondeo                │ (B) envío de Reverb
      │  GET /…/live (≤30s)       │  evento WS 'tick'
      │  repinta solo si rev↑     │  ShouldBroadcastNow
   [controlador de Laravel]    [servidor Reverb]

Topología de Reverb

Elemento Valor Origen
Bibliotecas de cliente laravel-echo + pusher-js importación dinámica (excluidas del paquete principal)

Los detalles de conexión del WebSocket se configuran durante la instalación. El operador solo tiene que abrir la pantalla: no hay nada que configurar.


Cómo usarlo

Operadores — nada que hacer

Lo «en vivo» es automático. Deje una pantalla abierta y el sondeo traerá los últimos valores cada 30 segundos; si el WebSocket está activo, las pantallas dirigidas por eventos se actualizan al instante. Para ahorrar energía, el sondeo se pausa mientras la pestaña está en segundo plano y se reanuda cuando vuelve a ella.

Activar el WebSocket de Reverb (opcional)

El envío por WebSocket lo configura su contacto de despliegue en el momento de la instalación: no es un interruptor para el operador dentro de la consola. Si necesita envío en tiempo real, contacte con su administrador o con el proveedor.

Que el envío por WebSocket esté apagado no es un error. Es un interruptor de apagado intencionado: las pantallas en vivo siguen funcionando solo con sondeo.

Qué hace realmente el sondeo

// Patrón representativo (p. ej. service-overview)
poll_ms: 30000,
this._poll = setInterval(() => {
    if (this.live && !document.hidden) this.poll_tick();   // se omite si la pestaña está en segundo plano
}, this.poll_ms);
// poll_tick → GET /service/live → vuelve a renderizar solo cuando cambió el rev de la respuesta

El rev del lado del servidor es la señal de cambio más barata posible. Por ejemplo, la pantalla de métricas de servidor usa MAX(seq) de la tabla heredada server_status como su rev: el valor solo sube cuando el recolector inserta una instantánea nueva.

// App\Services\Metric\ServerMetricService::rev()
return (int) DB::connection('legacy')->table('server_status')->max('seq');

El único trabajo en vivo que usa el envío de Reverb: la emulación remota

La emulación remota de Diagnóstico de seguridad difunde un tick de progreso cada vez que termina un host.


Fuentes de datos

Archivo Papel
resources/js/echo.js El único constructor de Echo de la aplicación (SOT) — importación dinámica · comprobación de configuración → null · forceTLS en tiempo de ejecución
app/Support/Realtime.php Red de seguridad de la difusión (sonda fsockopen de up() · absorbedor de excepciones de fire())
routes/channels.php Callbacks de autorización de canales (por ahora solo el App.Models.User.{id} por defecto)
app/Events/InfrRemoteEmulateTick.php El único evento de difusión realmente en uso
el controlador …/live de cada pantalla + …Service::rev() carga útil en vivo para el sondeo + token de cambio

Realtime — defensa en dos capas (el WS puede morir sin matar el trabajo original)

// (1) up() — sonda fsockopen de 150 ms (memorizada por petición). El broadcastWhen() de un evento se apoya en esto,
//     de modo que, con Reverb caído, un evento ShouldBroadcastNow NO lanza una excepción en línea por timeout de conexión.
public static function up(): bool  // sondea a partir de la configuración (sin valores fijos en el código)

// (2) fire() — protege a quien llama incluso cuando Reverb está en pie pero rechaza (413, o 5xx mientras se reinicia).
//     Los fallos se envían con report() a Pulse Exceptions; el trabajo original (un resultado de análisis guardado) sigue teniendo éxito.
public static function fire(object $event): void

El broadcastWhen() de un evento devuelve Realtime::up(): si Reverb está apagado, omite el envío por completo.


Acceso

Autorización de canales

Tipo de canal Autorización
Canal público (infr.emulate.{runId}) ninguna: el token de capacidad runId es la concesión de acceso (imposible de adivinar)
canales private / presence (hoja de ruta de diseño) el callback de routes/channels.php comprueba el user_level de la sesión + el ámbito del rol

La tabla de canales en tiempo real de CLAUDE.md (private-infr.server.{id}, private-infr.threats, presence-infr.ops, …) es una hoja de ruta de diseño. La difusión implementada hoy es el único canal público infr.emulate.{runId}, y routes/channels.php solo registra el canal privado App.Models.User.{id} que trae el framework por defecto. Cuando se añadan canales private/presence, autorice siempre por user_level y ámbito (p. ej. infr.threats exige user_level>=2 && scope∋security).

Acceso a los endpoints de sondeo

Los endpoints de sondeo /{screen}/live heredan el control de nivel de lectura del controlador de su pantalla (demo=1, staff=5, admin=10; algunas áreas están protegidas por el middleware infr.level:N). Por ejemplo, el sondeo de respaldo de estado de la emulación remota (emulate-status) exige acceso de escritura (nivel ≥2). Consulte Niveles RBAC para la política completa.


Solución de problemas y preguntas frecuentes

P. Los WebSockets no conectan, pero la pantalla se sigue actualizando

Es lo esperado. Las pantallas en vivo son plenamente funcionales con sondeo sin ningún WS. Los WebSockets solo reducen la latencia de trabajos dirigidos por eventos, como la emulación remota.

P. He activado Reverb pero el navegador no se engancha

P. ¿El panel machaca el servidor o la base de datos?

P. ¿Puedo programar los daemons de tiempo real?

Nunca. No lance desde el planificador (Schedule::command(...)) daemons de bucle infinito como reverb:start, queue:work o pulse:check. Los procesos que nunca terminan se acumulan en cada tick y agotan el pool compartido de conexiones de MySQL (medido el 2026-08-06 con pulse:check: 169 acumulados en 16 horas → [1040] Too many connections, afectando a la base de datos de producción). Ejecute los daemons únicamente desde el panel persistente único del lanzador (desarrollo) o con supervisor/systemd (producción). Consulte Desarrollo · Observabilidad para la ubicación de los daemons.

P. ¿Cómo reinicio Reverb tras un cambio de código?

En producción, php artisan reverb:restart sin corte de servicio (o reinícielo bajo supervisor). En desarrollo, reinicie el panel del lanzador. Si el WS rechaza conexiones brevemente durante el reinicio, Realtime::fire() absorbe la excepción y el sondeo cubre el hueco.


Relacionado

헤더의 LIVE 표시 — 화면이 스스로 갱신되는 중
헤더의 LIVE 표시 — 화면이 스스로 갱신되는 중