mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-21 15:46:43 +00:00
feat(notifications): replace polling with WebSocket push
Eliminates the 5-second setInterval polling loop for notifications in EditorLayout. A persistent /ws/notifications WebSocket connection is opened on mount; the backend pushes each alert the instant dispatchAlert fires, with 5s auto-reconnect on close. Key changes: - NotificationService: injectable broadcaster callback (setBroadcaster) - DatabaseService.addNotificationHistory: returns full NotificationHistory record (with id/is_read) instead of void - index.ts: notificationSubscribers Set + /ws/notifications upgrade handler (JWT-verified, placed before remote proxy path) - EditorLayout: polling removed, WS connect/reconnect replaces it
This commit is contained in:
@@ -162,11 +162,48 @@ export default function EditorLayout() {
|
||||
}
|
||||
};
|
||||
|
||||
// Notification polling - independent of active node, runs once on mount
|
||||
// Notification WS push — load history once on mount, then receive live updates
|
||||
useEffect(() => {
|
||||
fetchNotifications();
|
||||
const notificationInterval = setInterval(fetchNotifications, 5000);
|
||||
return () => clearInterval(notificationInterval);
|
||||
|
||||
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const wsBase = `${wsProtocol}//${window.location.host}`;
|
||||
let ws: WebSocket | null = null;
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let isMounted = true;
|
||||
|
||||
const connect = () => {
|
||||
ws = new WebSocket(`${wsBase}/ws/notifications`);
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
try {
|
||||
const msg = JSON.parse(event.data);
|
||||
if (msg.type === 'notification' && msg.payload) {
|
||||
setNotifications(prev => [msg.payload, ...prev]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[WS notifications] parse error', e);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
if (isMounted) {
|
||||
reconnectTimer = setTimeout(connect, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = () => {
|
||||
ws?.close();
|
||||
};
|
||||
};
|
||||
|
||||
connect();
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
if (reconnectTimer) clearTimeout(reconnectTimer);
|
||||
ws?.close();
|
||||
};
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Re-fetch stacks whenever the active node changes (or becomes available on mount).
|
||||
|
||||
Reference in New Issue
Block a user