Sanitized mirror from private repository - 2026-04-18 11:19:59 UTC
This commit is contained in:
52
dashboard/ui/lib/use-sse.ts
Normal file
52
dashboard/ui/lib/use-sse.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import type { ActivityEvent } from "./types";
|
||||
|
||||
// Use same origin — Next.js rewrites /api/* to backend
|
||||
|
||||
export function useSSE(path: string, maxEvents: number = 30) {
|
||||
const [events, setEvents] = useState<ActivityEvent[]>([]);
|
||||
const retryTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let es: EventSource | null = null;
|
||||
|
||||
function connect() {
|
||||
es = new EventSource(path);
|
||||
|
||||
// Backend sends "init" with the full batch and "update" with new events
|
||||
es.addEventListener("init", (e: MessageEvent) => {
|
||||
try {
|
||||
const batch: ActivityEvent[] = JSON.parse(e.data);
|
||||
setEvents(batch.slice(0, maxEvents));
|
||||
} catch {
|
||||
// ignore malformed events
|
||||
}
|
||||
});
|
||||
|
||||
es.addEventListener("update", (e: MessageEvent) => {
|
||||
try {
|
||||
const batch: ActivityEvent[] = JSON.parse(e.data);
|
||||
setEvents((prev) => [...batch, ...prev].slice(0, maxEvents));
|
||||
} catch {
|
||||
// ignore malformed events
|
||||
}
|
||||
});
|
||||
|
||||
es.onerror = () => {
|
||||
es?.close();
|
||||
retryTimeout.current = setTimeout(connect, 5000);
|
||||
};
|
||||
}
|
||||
|
||||
connect();
|
||||
|
||||
return () => {
|
||||
es?.close();
|
||||
if (retryTimeout.current) clearTimeout(retryTimeout.current);
|
||||
};
|
||||
}, [path, maxEvents]);
|
||||
|
||||
return events;
|
||||
}
|
||||
Reference in New Issue
Block a user