import { useState, useEffect } from 'react'; import type { ClusterNode } from '../types'; export function useClusterState() { const [nodes, setNodes] = useState([]); const [isConnected, setIsConnected] = useState(false); useEffect(() => { let ws: WebSocket | null = null; let reconnectTimeout: ReturnType; let retryCount = 0; const maxRetryCount = 10; const baseDelay = 1000; const connect = () => { // Determine WS URL based on API base URL or window location const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const host = window.location.host; const wsBase = import.meta.env.VITE_API_BASE_URL ? import.meta.env.VITE_API_BASE_URL.replace(/^http/, 'ws') : `${protocol}//${host}`; ws = new WebSocket(`${wsBase}/api/v1/cluster/ws/state`); ws.onopen = () => { setIsConnected(true); retryCount = 0; // Reset retry count on successful connection }; ws.onmessage = (event) => { try { const data = JSON.parse(event.data); if (Array.isArray(data)) { setNodes(data); } } catch (e) { console.error("Error parsing cluster state websocket message", e); } }; ws.onclose = () => { setIsConnected(false); if (retryCount < maxRetryCount) { const delay = baseDelay * Math.pow(2, retryCount); retryCount++; console.log(`WebSocket closed. Reconnecting in ${delay}ms... (Attempt ${retryCount})`); reconnectTimeout = setTimeout(connect, delay); } else { console.error("Max WebSocket reconnect attempts reached."); } }; }; connect(); return () => { clearTimeout(reconnectTimeout); if (ws) { ws.close(); } }; }, []); return { nodes, isConnected }; }