Pretor/frontend/src/hooks/useClusterState.ts

67 lines
1.9 KiB
TypeScript

import { useState, useEffect } from 'react';
import type { ClusterNode } from '../types';
export function useClusterState() {
const [nodes, setNodes] = useState<ClusterNode[]>([]);
const [isConnected, setIsConnected] = useState(false);
useEffect(() => {
let ws: WebSocket | null = null;
let reconnectTimeout: ReturnType<typeof setTimeout>;
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 };
}