refactor(sse): improve error handling and connection cleanup

This commit is contained in:
jessy-david-dev
2026-04-14 16:32:32 +02:00
parent 90b14919c5
commit afe1dfd2d7
2 changed files with 22 additions and 7 deletions
+6 -2
View File
@@ -1,4 +1,4 @@
// GET /api/rooms/[code]/stream SSE : pousse l'état de la room en temps réel // GET /api/rooms/[code]/stream - SSE : pousse l'état de la room en temps réel
// Le client s'abonne une seule fois ; chaque saveRoom publie sur Redis et notifie ici. // Le client s'abonne une seule fois ; chaque saveRoom publie sur Redis et notifie ici.
import { NextRequest } from "next/server"; import { NextRequest } from "next/server";
@@ -47,7 +47,11 @@ export async function GET(
sub.on("error", () => { sub.on("error", () => {
clearInterval(keepAlive); clearInterval(keepAlive);
try { controller.close(); } catch { /* déjà fermé */ } try {
controller.close();
} catch {
/* déjà fermé */
}
sub.disconnect(); sub.disconnect();
}); });
}, },
+16 -5
View File
@@ -97,25 +97,36 @@ export function useMultiGame() {
es.onmessage = (e) => { es.onmessage = (e) => {
try { try {
setRoom(JSON.parse(e.data) as Room); setRoom(JSON.parse(e.data) as Room);
} catch { /* ignore */ } } catch {
/* ignore */
}
}; };
es.onerror = () => { es.onerror = () => {
// EventSource reconnecte automatiquement pas besoin de gérer manuellement // EventSource reconnecte automatiquement - pas besoin de gérer manuellement
}; };
} }
// Quand le tab redevient visible : heartbeat immédiat pour rafraîchir l'état // Quand le tab redevient visible : heartbeat immédiat pour rafraîchir l'état
useEffect(() => { useEffect(() => {
function onVisible() { function onVisible() {
if (document.visibilityState === "visible" && sseCodeRef.current && ssePidRef.current) { if (
document.visibilityState === "visible" &&
sseCodeRef.current &&
ssePidRef.current
) {
fetch(`/api/rooms/${sseCodeRef.current}`, { fetch(`/api/rooms/${sseCodeRef.current}`, {
method: "PATCH", method: "PATCH",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "heartbeat", playerId: ssePidRef.current }), body: JSON.stringify({
action: "heartbeat",
playerId: ssePidRef.current,
}),
}) })
.then((r) => r.json()) .then((r) => r.json())
.then((d) => { if ((d as { room: Room }).room) setRoom((d as { room: Room }).room); }) .then((d) => {
if ((d as { room: Room }).room) setRoom((d as { room: Room }).room);
})
.catch(() => {}); .catch(() => {});
} }
} }