-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse-room.ts
More file actions
78 lines (66 loc) · 1.99 KB
/
Copy pathuse-room.ts
File metadata and controls
78 lines (66 loc) · 1.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { useState, useEffect, useCallback, useRef } from "react";
import { logger } from "@/lib/logger";
import type { RoomDetail } from "@/types";
const FALLBACK_POLL_INTERVAL = 3_000;
export function useRoom(roomId: string) {
const [room, setRoom] = useState<RoomDetail | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const eventSourceRef = useRef<EventSource | null>(null);
const fetchRoom = useCallback(async () => {
try {
const res = await fetch(`/api/rooms/${roomId}`);
if (res.ok) {
const data = await res.json();
setRoom(data);
setError(null);
} else {
const errData = await res.json().catch(() => ({}));
setError(errData.message || "Failed to fetch room");
}
} catch (err) {
logger.error("Failed to fetch room:", err);
setError("Network error");
} finally {
setLoading(false);
}
}, [roomId]);
useEffect(() => {
fetchRoom();
// SSE setup
const eventSource = new EventSource(`/api/rooms/${roomId}/events`);
eventSourceRef.current = eventSource;
// Fallback polling — only activated when SSE disconnects
let pollTimer: ReturnType<typeof setInterval> | null = null;
const stopPolling = () => {
if (pollTimer) {
clearInterval(pollTimer);
pollTimer = null;
}
};
eventSource.onopen = () => {
stopPolling();
};
eventSource.addEventListener("room_update", () => {
fetchRoom();
stopPolling();
});
eventSource.onerror = () => {
if (!pollTimer) {
logger.warn("SSE connection lost, falling back to polling");
pollTimer = setInterval(fetchRoom, FALLBACK_POLL_INTERVAL);
}
};
return () => {
eventSource.close();
eventSourceRef.current = null;
if (pollTimer) clearInterval(pollTimer);
};
}, [roomId, fetchRoom]);
return {
room,
loading,
error,
refetch: fetchRoom,
};
}