feat: 实现重连功能

master
鱼星 3 weeks ago
parent 6543571b96
commit faaaf2d5bb

@ -1,8 +1,16 @@
import React, { useState, useEffect, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { updateSocketId, updateNodeStatus, updateEventListOld } from '@/store/ideContainer';
import {
updateSocketId,
updateNodeStatus,
updateEventListOld,
resetNodeStatus,
updateRuntimeId,
updateIsRunning
} from '@/store/ideContainer';
import useWebSocket from '@/hooks/useWebSocket';
import { isJSON, getUrlParams } from '@/utils/common';
import { buildRuntimeReconnectRequest } from '@/utils/runtimeReconnect';
import styles from './style/index.module.less';
import SideBar from './sideBar';
@ -17,7 +25,7 @@ import {
updateEventList,
updateGlobalVarList
} from '@/store/ideContainer';
import { getAppListBySceneId } from '@/api/apps';
import { getAppListBySceneId, reconnectRun } from '@/api/apps';
import { getProjectComp } from '@/api/scene';
import ProjectContainer from '@/pages/orchestration/project';
@ -64,9 +72,10 @@ function IDEContainer() {
// 用于跟踪已打开的tab保持组件状态
const [openedTabs, setOpenedTabs] = useState<Set<string>>(new Set());
const [subMenuData, setSubMenuData] = useState<any>({});
const { menuData, flowData, currentAppData } = useSelector((state) => state.ideContainer);
const { menuData, flowData, currentAppData, socketId } = useSelector((state) => state.ideContainer);
const dispatch = useDispatch();
const navBarRef = useRef<NavBarRef>(null);
const lastReconnectKeyRef = useRef('');
// 初始化WebSocket hook
const ws = useWebSocket({
@ -104,7 +113,9 @@ function IDEContainer() {
}
// 更新节点状态使用特殊的actionType标记这是运行时状态更新
// 如果后端提供了 appId则传递给 action 以确保更新正确的应用状态
dispatch(updateNodeStatus({ nodeId, status, appId, actionType: 'RUNTIME_UPDATE' }));
if (nodeId) {
dispatch(updateNodeStatus({ nodeId, status, appId, actionType: 'RUNTIME_UPDATE' }));
}
// 只有当存在runLog时才发送日志到logBar
if (runLog) {
@ -122,6 +133,52 @@ function IDEContainer() {
}
});
useEffect(() => {
const reconnectRequest = buildRuntimeReconnectRequest({
app: currentAppData,
socketId,
lastReconnectKey: lastReconnectKeyRef.current
});
if (!reconnectRequest) {
return;
}
let canceled = false;
lastReconnectKeyRef.current = reconnectRequest.reconnectKey;
const reconnectRuntime = async () => {
try {
dispatch(resetNodeStatus());
dispatch(updateRuntimeId(reconnectRequest.instanceId));
dispatch(updateIsRunning(true));
const res: any = await reconnectRun({
instanceId: reconnectRequest.instanceId,
newSocketId: reconnectRequest.newSocketId
});
const reconnectResult = res?.data || res;
if (!canceled && reconnectResult?.success === false) {
lastReconnectKeyRef.current = '';
Message.error(reconnectResult.message || '运行实例重连失败');
}
} catch (error) {
if (!canceled) {
lastReconnectKeyRef.current = '';
console.error('运行实例重连失败:', error);
Message.error('运行实例重连失败');
}
}
};
reconnectRuntime();
return () => {
canceled = true;
};
}, [currentAppData, socketId, dispatch]);
// 监听自定义事件,处理打开子节点标签页的逻辑
useEffect(() => {
const handleOpenSubNodeTab = async (event: CustomEvent) => {
@ -500,4 +557,4 @@ function IDEContainer() {
);
}
export default IDEContainer;
export default IDEContainer;

@ -0,0 +1,28 @@
function isScheduledRunning(app) {
return app && (app.scheduled === 1 || app.scheduled === '1' || app.scheduled === true);
}
function buildRuntimeReconnectRequest({ app, socketId, lastReconnectKey }) {
const instanceId = app && app.instanceId ? String(app.instanceId) : '';
const newSocketId = socketId ? String(socketId) : '';
const appKey = app && (app.id || app.key) ? String(app.id || app.key) : '';
if (!isScheduledRunning(app) || !instanceId || !newSocketId || !appKey) {
return null;
}
const reconnectKey = `${appKey}:${instanceId}:${newSocketId}`;
if (reconnectKey === lastReconnectKey) {
return null;
}
return {
instanceId,
newSocketId,
reconnectKey,
};
}
module.exports = {
buildRuntimeReconnectRequest,
};
Loading…
Cancel
Save