67 lines
1.9 KiB
TypeScript
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 };
|
|
}
|