feat: real-time gate messages via SSE + faster push/pull intervals

- Add Server-Sent Events endpoint at GET /api/mesh/gate/stream that
  broadcasts ALL gate events to connected frontends (privacy: no
  per-gate subscriptions, clients filter locally)
- Hook SSE broadcast into all gate event entry points: local append,
  peer push receiver, and pull loop
- Reduce push/pull intervals from 30s to 10s for faster relay sync
- Add useGateSSE hook for frontend EventSource integration
- GateView + MeshChat use SSE for instant refresh, polling demoted
  to 30s fallback

Latency: same-node instant, cross-node ~10s avg (was ~34s)
This commit is contained in:
anoracleofra-code
2026-03-27 09:35:53 -06:00
parent 40a3cbdfdc
commit c81d81ec41
4 changed files with 137 additions and 5 deletions
+33
View File
@@ -0,0 +1,33 @@
import { useEffect, useRef } from 'react';
import { API_BASE } from '@/lib/api';
/**
* Subscribe to the backend SSE gate-event stream.
* Delivers ALL gate events (encrypted blobs) — the client filters by gate_id locally.
* The server never learns which gates a client cares about (privacy-preserving broadcast).
*
* Falls back gracefully: if the stream fails the browser's EventSource auto-reconnects.
*/
export function useGateSSE(onEvent: (gateId: string) => void) {
const callbackRef = useRef(onEvent);
callbackRef.current = onEvent;
useEffect(() => {
const es = new EventSource(`${API_BASE}/api/mesh/gate/stream`);
es.onmessage = (e) => {
try {
const data = JSON.parse(e.data);
if (data.gate_id && typeof data.gate_id === 'string') {
callbackRef.current(data.gate_id);
}
} catch {
/* ignore parse errors */
}
};
// Browser auto-reconnects EventSource on error — no manual retry needed.
return () => es.close();
}, []);
}