refactor(sse): improve error handling and connection cleanup
This commit is contained in:
@@ -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
@@ -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(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user