Browse Source

refactor: 运行时长提取成组件

pull/216/head
zhaowei 9 months ago
parent
commit
08fce258b6
13 changed files with 91 additions and 167 deletions
  1. +35
    -0
      react-ui/src/components/RunDuration/index.tsx
  2. +0
    -19
      react-ui/src/pages/ActiveLearn/Instance/index.tsx
  3. +4
    -8
      react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx
  4. +0
    -19
      react-ui/src/pages/AutoML/Instance/index.tsx
  5. +4
    -11
      react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx
  6. +6
    -21
      react-ui/src/pages/AutoML/components/ExperimentInstanceList/instance.tsx
  7. +13
    -2
      react-ui/src/pages/AutoML/components/ExperimentList/index.tsx
  8. +2
    -18
      react-ui/src/pages/Experiment/Info/index.jsx
  9. +4
    -21
      react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx
  10. +6
    -21
      react-ui/src/pages/Experiment/components/ExperimentInstanceList/instance.tsx
  11. +13
    -2
      react-ui/src/pages/Experiment/index.jsx
  12. +1
    -20
      react-ui/src/pages/HyperParameter/Instance/index.tsx
  13. +3
    -5
      react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx

+ 35
- 0
react-ui/src/components/RunDuration/index.tsx View File

@@ -0,0 +1,35 @@
import { useServerTime } from '@/hooks/useServerTime';
import { elapsedTime } from '@/utils/date';
import React, { useEffect, useState } from 'react';

type RunDurationProps = {
createTime?: string;
finishTime?: string;
className?: string;
style?: React.CSSProperties;
};
function RunDuration({ createTime, finishTime, className, style }: RunDurationProps) {
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState<Date>(now());

// 定时刷新耗时
useEffect(() => {
if (finishTime) {
setCurrentTime(new Date(finishTime));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finishTime, now]);
return (
<span className={className} style={style}>
{elapsedTime(createTime, currentTime)}
</span>
);
}

export default RunDuration;

+ 0
- 19
react-ui/src/pages/ActiveLearn/Instance/index.tsx View File

@@ -1,6 +1,5 @@
import KFIcon from '@/components/KFIcon';
import { AutoMLTaskType, ExperimentStatus } from '@/enums';
import { useServerTime } from '@/hooks/useServerTime';
import { getActiveLearnInsReq } from '@/services/activeLearn';
import { NodeStatus } from '@/types';
import { parseJsonText } from '@/utils';
@@ -36,9 +35,6 @@ function ActiveLearnInstance() {
const params = useParams();
const instanceId = safeInvoke(Number)(params.id);
const evtSourceRef = useRef<EventSource | null>(null);
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState<Date>(now());
const finish_time = workflowStatus?.finishedAt;

useEffect(() => {
if (instanceId) {
@@ -50,20 +46,6 @@ function ActiveLearnInstance() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [instanceId]);

// 定时刷新耗时
useEffect(() => {
if (finish_time) {
setCurrentTime(new Date(finish_time));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finish_time, now]);

// 获取实验实例详情
const getExperimentInsInfo = async (isStatusDetermined: boolean) => {
const [res] = await to(getActiveLearnInsReq(instanceId));
@@ -171,7 +153,6 @@ function ActiveLearnInstance() {
className={styles['active-learn-instance__basic']}
info={experimentInfo}
runStatus={workflowStatus}
finishTime={currentTime}
isInstance
/>
),


+ 4
- 8
react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx View File

@@ -1,4 +1,5 @@
import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo';
import RunDuration from '@/components/RunDuration';
import { AutoMLTaskType, autoMLTaskTypeOptions } from '@/enums';
import { useComputingResource } from '@/hooks/useComputingResource';
import {
@@ -11,7 +12,6 @@ import {
import { ActiveLearnData } from '@/pages/ActiveLearn/types';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { type NodeStatus } from '@/types';
import { elapsedTime } from '@/utils/date';
import {
formatBoolean,
formatCodeConfig,
@@ -31,10 +31,9 @@ type BasicInfoProps = {
className?: string;
isInstance?: boolean;
runStatus?: NodeStatus;
finishTime?: Date;
};

function BasicInfo({ info, className, runStatus, finishTime, isInstance = false }: BasicInfoProps) {
function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfoProps) {
const getResourceDescription = useComputingResource()[1];
const basicDatas: BasicInfoData[] = useMemo(() => {
if (!info) {
@@ -215,12 +214,10 @@ function BasicInfo({ info, className, runStatus, finishTime, isInstance = false
{
label: '启动时间',
value: formatDate(info.create_time),
ellipsis: true,
},
{
label: '执行时长',
value: elapsedTime(info.create_time, finishTime),
ellipsis: true,
value: <RunDuration createTime={info.create_time} finishTime={runStatus.finishedAt} />,
},
{
label: '状态',
@@ -243,10 +240,9 @@ function BasicInfo({ info, className, runStatus, finishTime, isInstance = false
</div>
</Flex>
),
ellipsis: true,
},
];
}, [runStatus, info, finishTime]);
}, [runStatus, info]);

return (
<div className={classNames(styles['active-learn-basic'], className)}>


+ 0
- 19
react-ui/src/pages/AutoML/Instance/index.tsx View File

@@ -1,6 +1,5 @@
import KFIcon from '@/components/KFIcon';
import { AutoMLTaskType, AutoMLType, ExperimentStatus } from '@/enums';
import { useServerTime } from '@/hooks/useServerTime';
import { getExperimentInsReq } from '@/services/autoML';
import { NodeStatus } from '@/types';
import { parseJsonText } from '@/utils';
@@ -36,9 +35,6 @@ function AutoMLInstance() {
const params = useParams();
const instanceId = safeInvoke(Number)(params.id);
const evtSourceRef = useRef<EventSource | null>(null);
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState<Date>(now());
const finish_time = workflowStatus?.finishedAt;

useEffect(() => {
if (instanceId) {
@@ -50,20 +46,6 @@ function AutoMLInstance() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [instanceId]);

// 定时刷新耗时
useEffect(() => {
if (finish_time) {
setCurrentTime(new Date(finish_time));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finish_time, now]);

// 获取实验实例详情
const getExperimentInsInfo = async (isStatusDetermined: boolean) => {
const [res] = await to(getExperimentInsReq(instanceId));
@@ -174,7 +156,6 @@ function AutoMLInstance() {
className={styles['auto-ml-instance__basic']}
info={autoMLInfo}
runStatus={workflowStatus}
finishTime={currentTime}
isInstance
/>
),


+ 4
- 11
react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx View File

@@ -1,4 +1,5 @@
import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo';
import RunDuration from '@/components/RunDuration';
import {
AutoMLTaskType,
AutoMLType,
@@ -10,7 +11,6 @@ import { AutoMLData } from '@/pages/AutoML/types';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { type NodeStatus } from '@/types';
import { parseJsonText } from '@/utils';
import { elapsedTime } from '@/utils/date';
import { formatBoolean, formatDataset, formatDate, formatEnum } from '@/utils/format';
import { Flex } from 'antd';
import classNames from 'classnames';
@@ -40,16 +40,9 @@ type AutoMLBasicProps = {
className?: string;
isInstance?: boolean;
runStatus?: NodeStatus;
finishTime?: Date;
};

function AutoMLBasic({
info,
className,
runStatus,
finishTime,
isInstance = false,
}: AutoMLBasicProps) {
function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) {
const getResourceDescription = useComputingResource()[1];
const basicDatas: BasicInfoData[] = useMemo(() => {
if (!info) {
@@ -303,7 +296,7 @@ function AutoMLBasic({
},
{
label: '执行时长',
value: elapsedTime(info.create_time, finishTime),
value: <RunDuration createTime={info.create_time} finishTime={runStatus.finishedAt} />,
},
{
label: '状态',
@@ -328,7 +321,7 @@ function AutoMLBasic({
),
},
];
}, [runStatus, info, finishTime]);
}, [runStatus, info]);

return (
<div className={classNames(styles['auto-ml-basic'], className)}>


+ 6
- 21
react-ui/src/pages/AutoML/components/ExperimentInstanceList/instance.tsx View File

@@ -1,11 +1,11 @@
import RunDuration from '@/components/RunDuration';
import { ExperimentStatus } from '@/enums';
import { useServerTime } from '@/hooks/useServerTime';
import { useSSE, type MessageHandler } from '@/hooks/useSSE';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { ExperimentCompleted } from '@/utils/constant';
import { elapsedTime, formatDate } from '@/utils/date';
import { formatDate } from '@/utils/date';
import { Typography } from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
import React, { useCallback } from 'react';
import styles from './index.less';

type ExperimentInstanceProps = {
@@ -25,9 +25,6 @@ function ExperimentInstance({
argo_ins_ns,
experimentInsId,
}: ExperimentInstanceProps) {
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState<Date>(now());

const handleSSEMessage: MessageHandler = useCallback(
(experimentInsId: number, status: string, finish_time: string) => {
window.postMessage({
@@ -43,23 +40,11 @@ function ExperimentInstance({
);
useSSE(experimentInsId, status, argo_ins_name, argo_ins_ns, handleSSEMessage);

// 定时刷新耗时
useEffect(() => {
if (finish_time) {
setCurrentTime(new Date(finish_time));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finish_time, now]);

return (
<React.Fragment>
<div className={styles.description}>{elapsedTime(create_time, currentTime)}</div>
<div className={styles.description}>
<RunDuration createTime={create_time} finishTime={finish_time} />
</div>
<div className={styles.startTime}>
<Typography.Text ellipsis={{ tooltip: formatDate(create_time) }}>
{formatDate(create_time)}


+ 13
- 2
react-ui/src/pages/AutoML/components/ExperimentList/index.tsx View File

@@ -29,7 +29,7 @@ import {
} from 'antd';
import { type SearchProps } from 'antd/es/input';
import classNames from 'classnames';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import ExperimentInstanceList from '../ExperimentInstanceList';
import { ExperimentListType, experimentListConfig } from './config';
import styles from './index.less';
@@ -58,6 +58,7 @@ function ExperimentList({ type }: ExperimentListProps) {
},
);
const config = experimentListConfig[type];
const timerRef = useRef<ReturnType<typeof window.setTimeout> | undefined>();

// 获取自主机器学习或超参数自动优化列表
const getAutoMLList = useCallback(async () => {
@@ -140,7 +141,13 @@ function ExperimentList({ type }: ExperimentListProps) {
: v,
),
);
setTimeout(() => {

if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = undefined;
}

timerRef.current = setTimeout(() => {
refreshExperimentList();
}, 10000);
}
@@ -149,6 +156,10 @@ function ExperimentList({ type }: ExperimentListProps) {
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = undefined;
}
};
}, [refreshExperimentList]);



+ 2
- 18
react-ui/src/pages/Experiment/Info/index.jsx View File

@@ -16,6 +16,7 @@ import ParamsModal from '../components/ViewParamsModal';
import { experimentStatusInfo } from '../status';
import styles from './index.less';
import { useServerTime } from '@/hooks/useServerTime';
import RunDuration from '@/components/RunDuration';

let graph = null;

@@ -28,13 +29,10 @@ function ExperimentText() {
const [paramsModalOpen, openParamsModal, closeParamsModal] = useVisible(false);
const [propsDrawerOpen, openPropsDrawer, closePropsDrawer, propsDrawerOpenRef] =
useVisible(false);
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState(now());
const navigate = useNavigate();
const evtSourceRef = useRef();
const width = 110;
const height = 36;
const finish_time = experimentIns?.finish_time

useEffect(() => {
initGraph();
@@ -63,20 +61,6 @@ function ExperimentText() {
};
}, []);

// 定时刷新耗时
useEffect(() => {
if (finish_time) {
setCurrentTime(new Date(finish_time));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finish_time, now]);

// 获取流水线模版
const getWorkflow = async () => {
const [res] = await to(getWorkflowById(locationParams.workflowId));
@@ -492,7 +476,7 @@ function ExperimentText() {
</div>
<div className={styles['pipeline-container__top__info']}>
执行时长:
{elapsedTime(experimentIns?.create_time, currentTime)}
<RunDuration createTime={experimentIns?.create_time} finishTime={experimentIns?.finish_time} />
</div>
<div className={styles['pipeline-container__top__info']}>
状态:


+ 4
- 21
react-ui/src/pages/Experiment/components/ExperimentDrawer/index.tsx View File

@@ -1,11 +1,11 @@
import RunDuration from '@/components/RunDuration';
import { ExperimentStatus } from '@/enums';
import { useServerTime } from '@/hooks/useServerTime';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { PipelineNodeModelSerialize } from '@/types';
import { elapsedTime, formatDate } from '@/utils/date';
import { formatDate } from '@/utils/date';
import { CloseOutlined, DatabaseOutlined, ProfileOutlined } from '@ant-design/icons';
import { Drawer, Tabs, Typography } from 'antd';
import { useEffect, useMemo, useState } from 'react';
import { useMemo } from 'react';
import ExperimentParameter from '../ExperimentParameter';
import ExperimentResult from '../ExperimentResult';
import LogList from '../LogList';
@@ -42,23 +42,6 @@ const ExperimentDrawer = ({
instanceNodeStartTime,
instanceNodeEndTime,
}: ExperimentDrawerProps) => {
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState(now());

// 定时刷新耗时
useEffect(() => {
if (instanceNodeEndTime) {
setCurrentTime(new Date(instanceNodeEndTime));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [instanceNodeEndTime, now]);

// 如果性能有问题,可以进一步拆解
const items = useMemo(
() => [
@@ -160,7 +143,7 @@ const ExperimentDrawer = ({
</div>
<div className={styles['experiment-drawer__info']}>
耗时:
{elapsedTime(instanceNodeStartTime, currentTime)}
<RunDuration createTime={instanceNodeStartTime} finishTime={instanceNodeEndTime} />
</div>
</div>
<Tabs


+ 6
- 21
react-ui/src/pages/Experiment/components/ExperimentInstanceList/instance.tsx View File

@@ -1,11 +1,11 @@
import RunDuration from '@/components/RunDuration';
import { ExperimentStatus } from '@/enums';
import { useServerTime } from '@/hooks/useServerTime';
import { useSSE, type MessageHandler } from '@/hooks/useSSE';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { ExperimentCompleted } from '@/utils/constant';
import { elapsedTime, formatDate } from '@/utils/date';
import { formatDate } from '@/utils/date';
import { Typography } from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
import React, { useCallback } from 'react';
import styles from './index.less';

type ExperimentInstanceProps = {
@@ -25,9 +25,6 @@ function ExperimentInstance({
argo_ins_ns,
experimentInsId,
}: ExperimentInstanceProps) {
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState<Date>(now());

const handleSSEMessage: MessageHandler = useCallback(
(experimentInsId: number, status: string, finish_time: string) => {
window.postMessage({
@@ -43,24 +40,12 @@ function ExperimentInstance({
);
useSSE(experimentInsId, status, argo_ins_name, argo_ins_ns, handleSSEMessage);

// 定时刷新耗时
useEffect(() => {
if (finish_time) {
setCurrentTime(new Date(finish_time));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finish_time, now]);

return (
<React.Fragment>
<div className={styles.description}>
<div style={{ width: '50%' }}>{elapsedTime(create_time, currentTime)}</div>
<div style={{ width: '50%' }}>
<RunDuration createTime={create_time} finishTime={finish_time} />
</div>
<div style={{ width: '50%' }} className={styles.startTime}>
<Typography.Text ellipsis={{ tooltip: formatDate(create_time) }}>
{formatDate(create_time)}


+ 13
- 2
react-ui/src/pages/Experiment/index.jsx View File

@@ -21,7 +21,7 @@ import tableCellRender, { TableCellValueType } from '@/utils/table';
import { modalConfirm } from '@/utils/ui';
import { App, Button, ConfigProvider, Dropdown, Input, Space, Table, Tooltip } from 'antd';
import classNames from 'classnames';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ComparisonType } from './Comparison/config';
import AddExperimentModal from './components/AddExperimentModal';
@@ -54,6 +54,7 @@ function Experiment() {
},
);
const { message } = App.useApp();
const timerRef = useRef();

// 获取实验列表
const getExperimentList = useCallback(async () => {
@@ -126,7 +127,13 @@ function Experiment() {
: v,
),
);
setTimeout(() => {

if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = undefined;
}

timerRef.current = setTimeout(() => {
refreshExperimentList();
}, 10000);
}
@@ -135,6 +142,10 @@ function Experiment() {
window.addEventListener('message', handleMessage);
return () => {
window.removeEventListener('message', handleMessage);
if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = undefined;
}
};
}, [refreshExperimentList]);



+ 1
- 20
react-ui/src/pages/HyperParameter/Instance/index.tsx View File

@@ -1,6 +1,5 @@
import KFIcon from '@/components/KFIcon';
import { ExperimentStatus } from '@/enums';
import { useServerTime } from '@/hooks/useServerTime';
import { getRayInsReq } from '@/services/hyperParameter';
import { NodeStatus } from '@/types';
import { parseJsonText } from '@/utils';
@@ -36,9 +35,6 @@ function HyperParameterInstance() {
const params = useParams();
const instanceId = safeInvoke(Number)(params.id);
const evtSourceRef = useRef<EventSource | null>(null);
const [now] = useServerTime();
const [currentTime, setCurrentTime] = useState<Date>(now());
const finish_time = workflowStatus?.finishedAt;

useEffect(() => {
if (instanceId) {
@@ -50,20 +46,6 @@ function HyperParameterInstance() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [instanceId]);

// 定时刷新耗时
useEffect(() => {
if (finish_time) {
setCurrentTime(new Date(finish_time));
} else {
const timer = setInterval(() => {
setCurrentTime(now());
}, 1000);
return () => {
clearInterval(timer);
};
}
}, [finish_time, now]);

// 获取实验实例详情
const getExperimentInsInfo = async (isStatusDetermined: boolean) => {
const [res] = await to(getRayInsReq(instanceId));
@@ -71,7 +53,7 @@ function HyperParameterInstance() {
const info = res.data as HyperParameterInstanceData;
const { param, node_status, argo_ins_name, argo_ins_ns, status, create_time } = info;
// 解析配置参数
const paramJson = parseJsonText(param);
const paramJson = parseJsonText(param).data;
if (paramJson) {
// 实例详情返回的参数是字符串,需要转换
if (typeof paramJson.parameters === 'string') {
@@ -186,7 +168,6 @@ function HyperParameterInstance() {
className={styles['hyper-parameter-instance__basic']}
info={experimentInfo}
runStatus={workflowStatus}
finishTime={currentTime}
isInstance
/>
),


+ 3
- 5
react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx View File

@@ -1,4 +1,5 @@
import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo';
import RunDuration from '@/components/RunDuration';
import { hyperParameterOptimizedMode } from '@/enums';
import { useComputingResource } from '@/hooks/useComputingResource';
import { experimentStatusInfo } from '@/pages/Experiment/status';
@@ -8,7 +9,6 @@ import {
} from '@/pages/HyperParameter/components/CreateForm/utils';
import { HyperParameterData } from '@/pages/HyperParameter/types';
import { type NodeStatus } from '@/types';
import { elapsedTime } from '@/utils/date';
import {
formatCodeConfig,
formatDataset,
@@ -33,14 +33,12 @@ type HyperParameterBasicProps = {
className?: string;
isInstance?: boolean;
runStatus?: NodeStatus;
finishTime?: Date;
};

function HyperParameterBasic({
info,
className,
runStatus,
finishTime,
isInstance = false,
}: HyperParameterBasicProps) {
const getResourceDescription = useComputingResource()[1];
@@ -157,7 +155,7 @@ function HyperParameterBasic({
},
{
label: '执行时长',
value: elapsedTime(info.create_time, finishTime),
value: <RunDuration createTime={info.create_time} finishTime={runStatus.finishedAt} />,
ellipsis: true,
},
{
@@ -184,7 +182,7 @@ function HyperParameterBasic({
ellipsis: true,
},
];
}, [runStatus, info, finishTime]);
}, [runStatus, info]);

return (
<div className={classNames(styles['hyper-parameter-basic'], className)}>


Loading…
Cancel
Save