refactor🎨: (阅读代码):connection.ts增加注释

master
yetao 3 weeks ago
parent e33cf4b6b5
commit 33bb60eae5

@ -230,40 +230,55 @@ export class ConnectionManager {
* @param config * @param config
* @returns Promise * @returns Promise
*/ */
// 定义一个受保护的异步方法 _createConnection用于创建一个连接对象。
protected async _createConnection(name: string, config?: FileSystemConfig): Promise<Connection> { protected async _createConnection(name: string, config?: FileSystemConfig): Promise<Connection> {
// 创建一个日志作用域,用于记录创建连接的过程。
const logging = Logging.scope(`createConnection(${name},${config ? 'config' : 'undefined'})`); const logging = Logging.scope(`createConnection(${name},${config ? 'config' : 'undefined'})`);
// 记录正在为指定名称创建新连接的信息。
logging.info`Creating a new connection for '${name}'`; logging.info`Creating a new connection for '${name}'`;
// 动态导入 './connect' 模块中的 createSSH 和 calculateActualConfig 函数。
const { createSSH, calculateActualConfig } = await import('./connect'); const { createSSH, calculateActualConfig } = await import('./connect');
// Query and calculate the actual config // Query and calculate the actual config
// 查询并计算实际的配置。
config = config || (await loadConfigs()).find(c => c.name === name); config = config || (await loadConfigs()).find(c => c.name === name);
if (!config) throw new Error(`No configuration with name '${name}' found`); if (!config) throw new Error(`No configuration with name '${name}' found`);
// 计算实际的配置,如果没有配置则抛出错误。
const actualConfig = await calculateActualConfig(config); const actualConfig = await calculateActualConfig(config);
if (!actualConfig) throw new Error('Connection cancelled'); if (!actualConfig) throw new Error('Connection cancelled');
// Start the actual SSH connection // Start the actual SSH connection
// 创建实际的 SSH 连接。
const client = await createSSH(actualConfig); const client = await createSSH(actualConfig);
if (!client) throw new Error(`Could not create SSH session for '${name}'`); if (!client) throw new Error(`Could not create SSH session for '${name}'`);
// 记录远程版本信息。
logging.info`Remote version: ${(client as any)._remoteVer || 'N/A'}`; logging.info`Remote version: ${(client as any)._remoteVer || 'N/A'}`;
// Calculate shell config // Calculate shell config
// 计算 shell 配置。
let shellConfig: ShellConfig; let shellConfig: ShellConfig;
const [flagSCV, flagSCR] = getFlag("SHELL_CONFIG", config.flags) || []; const [flagSCV, flagSCR] = getFlag("SHELL_CONFIG", config.flags) || [];
if (flagSCV && typeof flagSCV === 'string') { if (flagSCV && typeof flagSCV === 'string') {
// 如果有强制的 shell 配置标志,使用指定的 shell 配置并记录相关信息。
logging.info`Using forced shell config '${flagSCV}' set by ${flagSCR}`; logging.info`Using forced shell config '${flagSCV}' set by ${flagSCR}`;
shellConfig = KNOWN_SHELL_CONFIGS[flagSCV]; shellConfig = KNOWN_SHELL_CONFIGS[flagSCV];
if (!shellConfig) throw new Error(`The forced shell config '${flagSCV}' does not exist`); if (!shellConfig) throw new Error(`The forced shell config '${flagSCV}' does not exist`);
} else { } else {
// 否则,异步计算 shell 配置。
shellConfig = await calculateShellConfig(client, logging); shellConfig = await calculateShellConfig(client, logging);
} }
// Query home directory // Query home directory
// 查询主目录。
let home: string | Error | null; let home: string | Error | null;
if (shellConfig.isWindows) { if (shellConfig.isWindows) {
// 在 Windows 环境下尝试获取用户主目录。
home = await tryCommand(client, "echo %USERPROFILE%").catch((e: Error) => e); home = await tryCommand(client, "echo %USERPROFILE%").catch((e: Error) => e);
if (home === null) home = new Error(`No output for "echo %USERPROFILE%"`); if (home === null) home = new Error(`No output for "echo %USERPROFILE%"`);
if (typeof home === 'string') home = home.trim(); if (typeof home === 'string') home = home.trim();
if (home === "%USERPROFILE%") home = new Error(`Non-substituted output for "echo %USERPROFILE%"`); if (home === "%USERPROFILE%") home = new Error(`Non-substituted output for "echo %USERPROFILE%"`);
} else { } else {
// 在非 Windows 环境下尝试获取用户主目录。
home = await tryEcho(client, shellConfig, '~').catch((e: Error) => e); home = await tryEcho(client, shellConfig, '~').catch((e: Error) => e);
} }
if (typeof home !== 'string') { if (typeof home !== 'string') {
// 如果无法获取主目录且 CHECK_HOME 标志为 true则抛出错误并显示错误信息。
const [flagCH] = getFlagBoolean('CHECK_HOME', true, config.flags); const [flagCH] = getFlagBoolean('CHECK_HOME', true, config.flags);
logging.error('Could not detect home directory', LOGGING_NO_STACKTRACE); logging.error('Could not detect home directory', LOGGING_NO_STACKTRACE);
if (flagCH) { if (flagCH) {
@ -273,29 +288,32 @@ export class ConnectionManager {
await vscode.window.showErrorMessage(`Couldn't detect the home directory for '${name}'`, 'Okay'); await vscode.window.showErrorMessage(`Couldn't detect the home directory for '${name}'`, 'Okay');
throw new Error(`Could not detect home directory`); throw new Error(`Could not detect home directory`);
} else { } else {
// 如果 CHECK_HOME 标志为 false则记录警告信息并将主目录设置为空字符串。
if (home) logging.warning(home); if (home) logging.warning(home);
logging.warning('The CHECK_HOME flag is disabled, default to \'/\' and ignore the error'); logging.warning('The CHECK_HOME flag is disabled, default to \'/\' and ignore the error');
home = ''; home = '';
} }
} }
logging.debug`Home path: ${home}`; logging.debug`Home path: ${home}`;
// Calculate the environment // 计算环境变量。
const environment: EnvironmentVariable[] = mergeEnvironment([], config.environment); const environment: EnvironmentVariable[] = mergeEnvironment([], config.environment);
// Set up stuff for receiving remote commands // 根据 REMOTE_COMMANDS 标志设置接收远程命令的配置。
const [flagRCV, flagRCR] = getFlagBoolean('REMOTE_COMMANDS', false, actualConfig.flags); const [flagRCV, flagRCR] = getFlagBoolean('REMOTE_COMMANDS', false, actualConfig.flags);
if (flagRCV) { if (flagRCV) {
const [flagRCDV, flagRCDR] = getFlagBoolean('DEBUG_REMOTE_COMMANDS', false, actualConfig.flags); const [flagRCDV, flagRCDR] = getFlagBoolean('DEBUG_REMOTE_COMMANDS', false, actualConfig.flags);
const withDebugStr = flagRCDV? ` with debug logging enabled by '${flagRCDR}'` : ''; const withDebugStr = flagRCDV? ` with debug logging enabled by '${flagRCDR}'` : '';
logging.info`Flag REMOTE_COMMANDS provided in '${flagRCR}', setting up command terminal${withDebugStr}`; logging.info`Flag REMOTE_COMMANDS provided in '${flagRCR}', setting up command terminal${withDebugStr}`;
if (shellConfig.isWindows) { if (shellConfig.isWindows) {
// 在 Windows 环境下记录不支持命令终端的错误信息。
logging.error(`Windows detected, command terminal is not yet supported`, LOGGING_NO_STACKTRACE); logging.error(`Windows detected, command terminal is not yet supported`, LOGGING_NO_STACKTRACE);
} else { } else {
// 在非 Windows 环境下创建命令终端并将其路径添加到环境变量中。
const cmdPath = await this._createCommandTerminal(client, shellConfig, name, flagRCDV); const cmdPath = await this._createCommandTerminal(client, shellConfig, name, flagRCDV);
environment.push({ key: 'KELVIN_SSHFS_CMD_PATH', value: cmdPath }); environment.push({ key: 'KELVIN_SSHFS_CMD_PATH', value: cmdPath });
} }
} }
logging.debug`Environment: ${environment}`; logging.debug`Environment: ${environment}`;
// Set up the Connection object // 创建连接对象并设置相关属性。
let timeoutCounter = 0; let timeoutCounter = 0;
const con: Connection = { const con: Connection = {
config, client, actualConfig, home, shellConfig, environment, config, client, actualConfig, home, shellConfig, environment,
@ -304,6 +322,7 @@ export class ConnectionManager {
cache: {}, cache: {},
pendingUserCount: 0, pendingUserCount: 0,
idleTimer: setInterval(() => { // Automatically close connection when idle for a while idleTimer: setInterval(() => { // Automatically close connection when idle for a while
// 自动关闭连接的定时器函数,当连接空闲一段时间后关闭连接。
timeoutCounter = timeoutCounter ? timeoutCounter - 1 : 0; timeoutCounter = timeoutCounter ? timeoutCounter - 1 : 0;
if (con.pendingUserCount) return; // Still got starting filesystems/terminals on this connection if (con.pendingUserCount) return; // Still got starting filesystems/terminals on this connection
con.filesystems = con.filesystems.filter(fs => !fs.closed && !fs.closing); con.filesystems = con.filesystems.filter(fs => !fs.closed && !fs.closing);
@ -311,35 +330,53 @@ export class ConnectionManager {
if (con.terminals.length) return; // Still got active terminals on this connection if (con.terminals.length) return; // Still got active terminals on this connection
if (timeoutCounter !== 1) return timeoutCounter = 2; if (timeoutCounter !== 1) return timeoutCounter = 2;
// timeoutCounter === 1, so it's been inactive for at least 5 seconds, close it! // timeoutCounter === 1, so it's been inactive for at least 5 seconds, close it!
// 连接空闲一段时间后关闭连接,并记录关闭原因。
this.closeConnection(con, 'Idle with no active filesystems/terminals'); this.closeConnection(con, 'Idle with no active filesystems/terminals');
}, 5e3), }, 5e3),
}; };
// 将连接对象添加到连接列表中,并触发连接添加事件。
this.connections.push(con); this.connections.push(con);
this.onConnectionAddedEmitter.fire(con); this.onConnectionAddedEmitter.fire(con);
// 返回创建的连接对象。
return con; return con;
} }
// 定义一个公共的异步方法 createConnection用于创建一个连接对象。
public async createConnection(name: string, config?: FileSystemConfig): Promise<Connection> { public async createConnection(name: string, config?: FileSystemConfig): Promise<Connection> {
// 尝试获取已激活的连接对象,如果存在则直接返回。
const con = this.getActiveConnection(name, config); const con = this.getActiveConnection(name, config);
if (con) return con; if (con) return con;
// 检查是否有正在等待的连接,如果有则直接返回等待中的连接对象。
let pending = this.pendingConnections[name]; let pending = this.pendingConnections[name];
if (pending) return pending[0]; if (pending) return pending[0];
// 创建一个等待中的连接对象,并将其和配置一起存储在 pendingConnections 中。
pending = [this._createConnection(name, config), config]; pending = [this._createConnection(name, config), config];
this.pendingConnections[name] = pending; this.pendingConnections[name] = pending;
// 触发正在等待的连接发生变化的事件。
this.onPendingChangedEmitter.fire(); this.onPendingChangedEmitter.fire();
// 当等待中的连接完成时,删除对应的等待项并触发事件。
pending[0].finally(() => { pending[0].finally(() => {
delete this.pendingConnections[name]; delete this.pendingConnections[name];
this.onPendingChangedEmitter.fire(); this.onPendingChangedEmitter.fire();
}); });
// 返回等待中的连接对象。
return pending[0]; return pending[0];
} }
// 定义一个公共方法 closeConnection用于关闭指定的连接。
public closeConnection(connection: Connection, reason?: string) { public closeConnection(connection: Connection, reason?: string) {
// 查找连接在连接列表中的索引,如果不存在则直接返回。
const index = this.connections.indexOf(connection); const index = this.connections.indexOf(connection);
if (index === -1) return; if (index === -1) return;
// 如果有原因则格式化原因字符串,否则设置为'no reason given'。
reason = reason ? `'${reason}' as reason` : ' no reason given'; reason = reason ? `'${reason}' as reason` : ' no reason given';
// 记录关闭连接的信息,包括连接的名称和关闭原因。
Logging.info`Closing connection to '${connection.actualConfig.name}' with ${reason}`; Logging.info`Closing connection to '${connection.actualConfig.name}' with ${reason}`;
// 从连接列表中移除指定的连接。
this.connections.splice(index, 1); this.connections.splice(index, 1);
// 清除连接的空闲定时器。
clearInterval(connection.idleTimer); clearInterval(connection.idleTimer);
// 触发连接被移除的事件。
this.onConnectionRemovedEmitter.fire(connection); this.onConnectionRemovedEmitter.fire(connection);
// 关闭连接的客户端。
connection.client.end(); connection.client.end();
} }
// Without making createConnection return a Proxy, or making Connection a class with // Without making createConnection return a Proxy, or making Connection a class with
@ -347,8 +384,11 @@ export class ConnectionManager {
// So stuff that updates connections should inform us by calling this method. // So stuff that updates connections should inform us by calling this method.
// (currently the only thing this matters for is the 'sshfs-connections' tree view) // (currently the only thing this matters for is the 'sshfs-connections' tree view)
// The updater callback just allows for syntactic sugar e.g. update(con, con => modifyCon(con)) // The updater callback just allows for syntactic sugar e.g. update(con, con => modifyCon(con))
// 定义一个公共方法 update用于更新指定的连接。
public update(connection: Connection, updater?: (con: Connection) => void) { public update(connection: Connection, updater?: (con: Connection) => void) {
// 如果提供了更新函数,则调用更新函数对连接进行更新。
updater?.(connection); updater?.(connection);
// 触发连接被更新的事件。
this.onConnectionUpdatedEmitter.fire(connection); this.onConnectionUpdatedEmitter.fire(connection);
} }
} }

Loading…
Cancel
Save