feat: 挂起状态下禁止自动重连
This commit is contained in:
@@ -21,7 +21,7 @@ export function createWebSocketConnectionManager(
|
|||||||
sessionId: string,
|
sessionId: string,
|
||||||
dbConnectionId: string,
|
dbConnectionId: string,
|
||||||
t: ReturnType<typeof useI18n>['t'],
|
t: ReturnType<typeof useI18n>['t'],
|
||||||
options?: { isResumeFlow?: boolean }
|
options?: { isResumeFlow?: boolean; getIsMarkedForSuspend?: () => boolean } // +++ 添加 getIsMarkedForSuspend 回调 +++
|
||||||
) {
|
) {
|
||||||
// --- Instance State ---
|
// --- Instance State ---
|
||||||
// 每个实例拥有独立的 WebSocket 对象、状态和消息处理器
|
// 每个实例拥有独立的 WebSocket 对象、状态和消息处理器
|
||||||
@@ -33,6 +33,7 @@ export function createWebSocketConnectionManager(
|
|||||||
const messageHandlers = new Map<string, Set<MessageHandler>>(); // 此实例的消息处理器注册表
|
const messageHandlers = new Map<string, Set<MessageHandler>>(); // 此实例的消息处理器注册表
|
||||||
const instanceSessionId = sessionId; // 保存会话 ID 用于日志
|
const instanceSessionId = sessionId; // 保存会话 ID 用于日志
|
||||||
const instanceDbConnectionId = dbConnectionId; // 保存数据库连接 ID
|
const instanceDbConnectionId = dbConnectionId; // 保存数据库连接 ID
|
||||||
|
const getIsMarkedForSuspend = options?.getIsMarkedForSuspend; // +++ 获取回调函数 +++
|
||||||
let reconnectAttempts = 0; // 重连尝试次数
|
let reconnectAttempts = 0; // 重连尝试次数
|
||||||
const maxReconnectAttempts = 5; // 最大重连次数
|
const maxReconnectAttempts = 5; // 最大重连次数
|
||||||
let reconnectTimeoutId: ReturnType<typeof setTimeout> | null = null; // 重连定时器 ID
|
let reconnectTimeoutId: ReturnType<typeof setTimeout> | null = null; // 重连定时器 ID
|
||||||
@@ -80,6 +81,14 @@ export function createWebSocketConnectionManager(
|
|||||||
const scheduleReconnect = () => {
|
const scheduleReconnect = () => {
|
||||||
if (intentionalDisconnect) return; // 如果是主动断开,则不重连
|
if (intentionalDisconnect) return; // 如果是主动断开,则不重连
|
||||||
|
|
||||||
|
// +++ 检查是否标记为待挂起 +++
|
||||||
|
if (getIsMarkedForSuspend && getIsMarkedForSuspend()) {
|
||||||
|
console.log(`[WebSocket ${instanceSessionId}] 会话已标记为待挂起,不执行自动重连。`);
|
||||||
|
statusMessage.value = getStatusText('markedForSuspendNoReconnect'); // 可以为此添加新的i18n文本
|
||||||
|
connectionStatus.value = 'disconnected'; // 保持断开状态或设为特定状态
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (reconnectAttempts >= maxReconnectAttempts) {
|
if (reconnectAttempts >= maxReconnectAttempts) {
|
||||||
console.log(`[WebSocket ${instanceSessionId}] 已达到最大重连次数 (${maxReconnectAttempts}),停止重连。`);
|
console.log(`[WebSocket ${instanceSessionId}] 已达到最大重连次数 (${maxReconnectAttempts}),停止重连。`);
|
||||||
statusMessage.value = getStatusText('reconnectFailed');
|
statusMessage.value = getStatusText('reconnectFailed');
|
||||||
|
|||||||
@@ -44,12 +44,36 @@ export const openNewSession = (
|
|||||||
|
|
||||||
// 1. 创建管理器实例
|
// 1. 创建管理器实例
|
||||||
const isResume = !!existingSessionId; // 如果提供了 existingSessionId,则为恢复流程
|
const isResume = !!existingSessionId; // 如果提供了 existingSessionId,则为恢复流程
|
||||||
|
|
||||||
|
// 稍后创建 wsManager,先创建 SessionState 对象的一部分
|
||||||
|
const newSessionPartial: Omit<SessionState, 'wsManager' | 'sftpManagers' | 'terminalManager' | 'statusMonitorManager' | 'dockerManager'> & { wsManager?: WsManagerInstance } = {
|
||||||
|
sessionId: newSessionId,
|
||||||
|
connectionId: dbConnId,
|
||||||
|
connectionName: connInfo.name || connInfo.host,
|
||||||
|
editorTabs: ref([]),
|
||||||
|
activeEditorTabId: ref(null),
|
||||||
|
commandInputContent: ref(''),
|
||||||
|
isMarkedForSuspend: false,
|
||||||
|
disposables: [],
|
||||||
|
};
|
||||||
|
|
||||||
const wsManager = createWebSocketConnectionManager(
|
const wsManager = createWebSocketConnectionManager(
|
||||||
newSessionId,
|
newSessionId, // 这个 sessionId 在 wsManager 内部使用,可能与 SessionState.sessionId 不同步(如果后者被后端更新)
|
||||||
dbConnId,
|
dbConnId,
|
||||||
t,
|
t,
|
||||||
{ isResumeFlow: isResume } // 传递 isResumeFlow 选项
|
{
|
||||||
|
isResumeFlow: isResume,
|
||||||
|
getIsMarkedForSuspend: () => {
|
||||||
|
// 直接从 newSessionPartial (它将成为完整的 SessionState 对象) 读取状态
|
||||||
|
// 注意:如果 SessionState.sessionId 被后端更新,而 wsManager 内部的 sessionId (instanceSessionId)
|
||||||
|
// 没有相应更新并在 scheduleReconnect 中使用 instanceSessionId 来识别日志,可能会有轻微不一致。
|
||||||
|
// 但对于 isMarkedForSuspend 的判断是准确的。
|
||||||
|
return !!newSessionPartial.isMarkedForSuspend;
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
newSessionPartial.wsManager = wsManager; // 将 wsManager 添加回部分对象
|
||||||
|
|
||||||
const sshTerminalDeps: SshTerminalDependencies = {
|
const sshTerminalDeps: SshTerminalDependencies = {
|
||||||
sendMessage: wsManager.sendMessage,
|
sendMessage: wsManager.sendMessage,
|
||||||
onMessage: wsManager.onMessage,
|
onMessage: wsManager.onMessage,
|
||||||
@@ -68,22 +92,16 @@ export const openNewSession = (
|
|||||||
};
|
};
|
||||||
const dockerManager = createDockerManager(newSessionId, dockerManagerDeps, { t });
|
const dockerManager = createDockerManager(newSessionId, dockerManagerDeps, { t });
|
||||||
|
|
||||||
// 2. 创建 SessionState 对象
|
// 2. 完成 SessionState 对象
|
||||||
const newSession: SessionState = {
|
const newSession: SessionState = {
|
||||||
sessionId: newSessionId,
|
...newSessionPartial, // 包含 sessionId, connectionId, connectionName, wsManager, editorTabs, etc.
|
||||||
connectionId: dbConnId,
|
wsManager: wsManager, // 确保 wsManager 被正确赋值
|
||||||
connectionName: connInfo.name || connInfo.host,
|
sftpManagers: new Map<string, SftpManagerInstance>(),
|
||||||
wsManager: wsManager,
|
|
||||||
sftpManagers: new Map<string, SftpManagerInstance>(), // 初始化 Map
|
|
||||||
terminalManager: terminalManager,
|
terminalManager: terminalManager,
|
||||||
statusMonitorManager: statusMonitorManager,
|
statusMonitorManager: statusMonitorManager,
|
||||||
dockerManager: dockerManager,
|
dockerManager: dockerManager,
|
||||||
editorTabs: ref([]),
|
|
||||||
activeEditorTabId: ref(null),
|
|
||||||
commandInputContent: ref(''),
|
|
||||||
isMarkedForSuspend: false, // +++ 初始化 isMarkedForSuspend状态 +++
|
|
||||||
disposables: [], // 初始化 disposables 数组
|
|
||||||
};
|
};
|
||||||
|
// newSession.isMarkedForSuspend 已经在 newSessionPartial 中初始化为 false
|
||||||
|
|
||||||
// 3. 添加到 Map 并激活
|
// 3. 添加到 Map 并激活
|
||||||
const newSessionsMap = new Map(sessions.value);
|
const newSessionsMap = new Map(sessions.value);
|
||||||
|
|||||||
Reference in New Issue
Block a user