* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
import {
DataRequest,
ModuleName,
ConnectHost,
GLOBAL_HOST,
Project,
FileOrDirectory,
ImportResultBody,
DataSource,
LayerType, ImportTreeInfo, type Response,
} from './websocket/defs';
import { Connection, ErrorMsg } from './websocket/connection';
import connector from '@/connection';
import {
importProject,
ImportProjectParams,
} from '@/utils/Request';
import { ProjectAction, SessionAction, ProjectType } from '@/utils/enum';
import { updateRankMap } from '@/utils/Rank';
import { transformFile, updateProject } from '@/utils/Project';
import { closeLoading } from '@/utils/useLoading';
import { updateDataScene } from '@/components/TabPane/Index';
import { Session } from '@/entity/session';
import { errorCenter, RequestOptions, WsError } from '@insight/lib';
export const CONNECTION_MAP: Map<string, Connection> = new Map();
const getConnectionMapKey = (host: ConnectHost): string => {
return `${host?.remote}:${host?.port}`;
};
export const connectRemote = async function (host: ConnectHost): Promise<boolean> {
const connection = new Connection(host);
try {
await connection.connect();
} catch (e) {
return false;
}
CONNECTION_MAP.set(getConnectionMapKey(host), connection);
return true;
};
export const isExistedRemote = function(host: ConnectHost): boolean {
return CONNECTION_MAP.has(getConnectionMapKey(host));
};
export const addDataPath = async function(project: Project, action: ProjectAction, isConflict: boolean, session: Session): Promise<boolean> {
if (!isExistedRemote(GLOBAL_HOST)) {
const connected = await connectRemote(GLOBAL_HOST);
if (!connected) {
return false;
}
}
const connection = CONNECTION_MAP.get(getConnectionMapKey(GLOBAL_HOST));
if (connection) {
connector.send({
event: 'remote/savePageSetting',
body: {},
target: 'plugin',
});
const params: ImportProjectParams = {
projectName: project.projectName,
path: project.projectPath,
selectedFileType: project.selectedFileType,
selectedFilePath: project.selectedFilePath,
selectedRankId: project.selectedRankId,
projectAction: action,
isConflict,
};
const { body: result, error } = await importProject(params) as Response<ImportResultBody>;
if (error) {
const { code, message } = error;
errorCenter.handleError(new WsError(code, message));
}
if (!result) {
connector.send({ event: 'remote/reset', body: {}, target: 'plugin' });
return false;
}
const res = result;
if (session.actionListener.type !== SessionAction.ADD_DATA_UNDER_PROJECT && (res.reset || res.isCluster)) {
session.reset();
}
session.resetActionListener();
const { activeDataSource } = session;
const switchProject = params?.projectAction !== ProjectAction.ADD_FILE || activeDataSource?.projectName !== params?.projectName;
connector.send({
event: 'remote/import',
body: { dataSource: transformTimelineDataSource(project), importResult: res, switchProject },
target: 'plugin',
});
afterImportProject(params, res);
}
return true;
};
const transformTimelineDataSource = (project: Project): DataSource => {
const data = { ...GLOBAL_HOST, ...project, dataPath: project.projectPath };
return data as DataSource;
};
* 递归查找 rank 列表
* @param children
*/
const reduceImportRankInfoList = (children: ImportTreeInfo[] = []): Array<{ rankId: string; filePath: string }> => {
const reduceFunc = (item: ImportTreeInfo, depth: number): Array<{ rankId: string; filePath: string }> => {
if (depth >= 5) {
return [];
}
if (item.type === 'RANK' || item.type === 'COMPUTE' || item.type === 'IPYNB') {
return [{ rankId: item.rankId ?? '', filePath: item.filePath }];
} else {
return item.children.flatMap((child) => reduceFunc(child, depth + 1));
}
};
return children.flatMap((child) => reduceFunc(child, 0));
};
* 导入项目后更新项目管理器操作
* @param params 请求体
* @param data 返回值
*/
const afterImportProject = (params: ImportProjectParams, data: ImportResultBody): void => {
try {
const projectAction = params.projectAction as ProjectAction;
const hasConflict = params.isConflict as boolean;
const projectName = params.projectName;
const projectPath = params.path;
const importRankList = reduceImportRankInfoList(data.children);
let targetList = importRankList;
if (data.isCluster && data.isIE) {
const subOfNotIE = data.children.filter(item => item.projectType !== ProjectType.IE);
targetList = reduceImportRankInfoList(subOfNotIE);
}
const selectedFilePath = params.selectedFilePath ?? targetList?.[0]?.filePath ?? '';
const selectedRankId = params.selectedRankId ?? targetList?.[0]?.rankId ?? '';
const selectedFileType: LayerType = params.selectedFileType ?? 'RANK';
const children = data.children?.map((child) => transformFile(child, 0))
?.flat()?.filter((item) => item !== undefined) as FileOrDirectory[];
updateDataScene(data);
updateRankMap(projectAction, projectName, importRankList);
updateProject({ projectAction, projectName, children, hasConflict, projectPath, selectedFileType, selectedFilePath, selectedRankId });
} catch (error) {
console.error(error);
}
closeLoading();
};
export const request = async <T>(
moduleName: ModuleName,
args: DataRequest,
options?: RequestOptions,
): Promise<T | ErrorMsg> => {
const connection: Connection | undefined = CONNECTION_MAP.get(getConnectionMapKey(GLOBAL_HOST));
if (connection === undefined) {
return Promise.reject(Error('no connection'));
}
const res = await connection?.fetch<T>(moduleName, args);
if ((res as Response)?.command === 'import/action') {
return res;
}
if ((res as ErrorMsg).error) {
const { error: { code, message } } = res as ErrorMsg;
const wsError = new WsError(code, message);
if (!options?.silent) {
errorCenter.handleError(wsError);
}
throw wsError;
}
return res;
};
export const requestModule = function <T>(
moduleName: ModuleName,
args: DataRequest,
): Promise<T | ErrorMsg> {
const connection: Connection | undefined = CONNECTION_MAP.get(getConnectionMapKey(GLOBAL_HOST));
if (connection === undefined) {
return Promise.reject(Error('no connection'));
}
return connection?.fetch<T>(moduleName, args);
};