Unverified Commit 11b97adb authored by xiaoguaiguai's avatar xiaoguaiguai Committed by GitHub

add job CheckPoint History for Recovery of CheckPoint (#665)

parent db71177f
......@@ -25,6 +25,9 @@ export function parseNumStr(num: number) {
}
export function parseMilliSecondStr(second_time: number) {
if(((second_time/1000) %60) < 1){
return second_time + "毫秒";
}
return parseSecondStr(second_time/1000);
}
......
import {Descriptions, Empty, Tabs, Tag} from 'antd';
import {Button, Descriptions, Empty, Modal, Tabs, Tag} from 'antd';
import {
CheckCircleOutlined,
CloseCircleOutlined,
ExclamationCircleOutlined,
MinusCircleOutlined,
RocketOutlined,
SyncOutlined
} from "@ant-design/icons";
import {parseByteStr, parseMilliSecondStr, parseSecondStr} from "@/components/Common/function";
import ProTable, {ActionType, ProColumns} from "@ant-design/pro-table";
import {useRef} from "react";
import {CheckPointsDetailInfo} from "@/pages/DevOps/data";
const {TabPane} = Tabs;
const CheckPoints = (props: any) => {
const {job} = props;
const actionRef = useRef<ActionType>();
const getOverview = () => {
return (
<>
{(job?.jobHistory?.checkpoints) ?
<Descriptions bordered size="small" column={1} >
<Descriptions bordered size="small" column={1}>
<Descriptions.Item label="CheckPoint Counts">
<Tag color="blue" title={"Total"}>
<RocketOutlined/> Total: {job?.jobHistory?.checkpoints['counts']['total']}
</Tag>
<Tag color="red" title={"Failed"}>
<CloseCircleOutlined /> Failed: {job?.jobHistory?.checkpoints['counts']['failed']}
<CloseCircleOutlined/> Failed: {job?.jobHistory?.checkpoints['counts']['failed']}
</Tag>
<Tag color="cyan" title={"Restored"}>
<ExclamationCircleOutlined /> Restored: {job?.jobHistory?.checkpoints['counts']['restored']}
<ExclamationCircleOutlined/> Restored: {job?.jobHistory?.checkpoints['counts']['restored']}
</Tag>
<Tag color="green" title={"Completed"}>
<CheckCircleOutlined /> Completed: {job?.jobHistory?.checkpoints['counts']['completed']}
<CheckCircleOutlined/> Completed: {job?.jobHistory?.checkpoints['counts']['completed']}
</Tag>
<Tag color="orange" title={"In Progress"}>
<SyncOutlined /> In Progress: {job?.jobHistory?.checkpoints['counts']['in_progress']}
<SyncOutlined spin/> In Progress: {job?.jobHistory?.checkpoints['counts']['in_progress']}
</Tag>
</Descriptions.Item>
......@@ -47,7 +51,7 @@ const CheckPoints = (props: any) => {
<Descriptions.Item label="Latest Failed CheckPoint">
<Tag color="red" title={"Latest Failed CheckPoint"}>
{job?.jobHistory?.checkpoints['latest']['failed']=== null ? 'None' :
{job?.jobHistory?.checkpoints['latest']['failed'] === null ? 'None' :
job?.jobHistory?.checkpoints['latest']['failed']['external_path']
}
</Tag>
......@@ -56,7 +60,7 @@ const CheckPoints = (props: any) => {
<Descriptions.Item label="Latest Restored">
<Tag color="cyan" title={"Latest Restored"}>
{job?.jobHistory?.checkpoints['latest']['restored'] === null ? 'None' :
job?.jobHistory?.checkpoints['latest']['restored']['external_path'] }
job?.jobHistory?.checkpoints['latest']['restored']['external_path']}
</Tag>
</Descriptions.Item>
......@@ -81,28 +85,28 @@ const CheckPoints = (props: any) => {
return (
<>
{(job?.jobHistory?.checkpoints) ?
<Descriptions bordered size="small" column={1} >
<Descriptions bordered size="small" column={1}>
<Descriptions.Item label="End to End Duration">
<Tag color="blue" title={"Max"}>
<RocketOutlined/> Max: {parseSecondStr(job?.jobHistory?.checkpoints['summary']['end_to_end_duration']['max']) }
<RocketOutlined/> Max: {parseSecondStr(job?.jobHistory?.checkpoints['summary']['end_to_end_duration']['max'])}
</Tag>
<Tag color="green" title={"Min"}>
<RocketOutlined/> Min: {parseSecondStr(job?.jobHistory?.checkpoints['summary']['end_to_end_duration']['min']) }
<RocketOutlined/> Min: {parseSecondStr(job?.jobHistory?.checkpoints['summary']['end_to_end_duration']['min'])}
</Tag>
<Tag color="orange" title={"Avg"}>
<RocketOutlined/> Avg: {parseSecondStr(job?.jobHistory?.checkpoints['summary']['end_to_end_duration']['avg']) }
<RocketOutlined/> Avg: {parseSecondStr(job?.jobHistory?.checkpoints['summary']['end_to_end_duration']['avg'])}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Checkpointed Data Size">
<Tag color="blue" title={"Max"}>
<RocketOutlined/> Max: {parseByteStr(job?.jobHistory?.checkpoints['summary']['state_size']['max']) }
<RocketOutlined/> Max: {parseByteStr(job?.jobHistory?.checkpoints['summary']['state_size']['max'])}
</Tag>
<Tag color="green" title={"Min"}>
<RocketOutlined/> Min: {parseByteStr(job?.jobHistory?.checkpoints['summary']['state_size']['min']) }
<RocketOutlined/> Min: {parseByteStr(job?.jobHistory?.checkpoints['summary']['state_size']['min'])}
</Tag>
<Tag color="orange" title={"Avg"}>
<RocketOutlined/> Avg: {parseByteStr(job?.jobHistory?.checkpoints['summary']['state_size']['avg']) }
<RocketOutlined/> Avg: {parseByteStr(job?.jobHistory?.checkpoints['summary']['state_size']['avg'])}
</Tag>
</Descriptions.Item>
......@@ -149,11 +153,126 @@ const CheckPoints = (props: any) => {
}
function recoveryCheckPoint(row: CheckPointsDetailInfo) {
Modal.confirm({
title: 'Recovery Of CheckPoint',
content: `确定从 CheckPoint 【${row.external_path}】恢复吗?`,
okText: '确认',
cancelText: '取消',
onOk: async () => {
// TODO: handleRecoveryCheckPoint
// await handleRecoveryCheckPoint('api/task/recoveryCheckPoint', [row]);
actionRef.current?.reload?.();
}
});
}
const getHistory = () => {
const checkPointsList: CheckPointsDetailInfo[] = [];
job?.jobHistory?.checkpoints['history']?.forEach((entity: CheckPointsDetailInfo) => {
return checkPointsList.push({
jobID: job?.id,
historyID: job?.jobHistory.id,
id: entity.id,
status: entity.status,
end_to_end_duration: entity.end_to_end_duration,
external_path: entity.external_path,
latest_ack_timestamp: entity.latest_ack_timestamp,
state_size: entity.state_size,
trigger_timestamp: entity.trigger_timestamp,
});
}
);
const columns: ProColumns<CheckPointsDetailInfo>[] = [
{
title: 'ID',
align: 'center',
dataIndex: 'id',
},
{
title: '状态',
align: 'center',
copyable: true,
render: (dom, entity) => {
if (entity.status === 'COMPLETED') {
return <Tag icon={<CheckCircleOutlined/>} color="success">{entity.status}</Tag>
}
if (entity.status === 'IN_PROGRESS') {
return <Tag icon={<SyncOutlined spin/>} color="processing">{entity.status}</Tag>
}
if (entity.status === 'FAILED') {
return <Tag icon={<CloseCircleOutlined/>} color="error">{entity.status}</Tag>
}
return <Tag icon={<MinusCircleOutlined/>} color="default">{entity.status}</Tag>
},
},
{
title: '耗时',
align: 'center',
copyable: true,
render: (dom, entity) => {
return entity.end_to_end_duration === null ? 'None' : parseMilliSecondStr(entity.end_to_end_duration);
},
},
{
title: '存储位置',
align: 'center',
copyable: true,
dataIndex: 'external_path',
},
{
title: '最后响应时间',
align: 'center',
dataIndex: 'latest_ack_timestamp',
valueType: 'dateTime',
},
{
title: '状态大小',
align: 'center',
render: (dom, entity) => {
return entity.state_size === null ? 'None' : parseByteStr(entity.state_size);
},
},
{
title: '触发时间',
align: 'center',
valueType: 'dateTime',
dataIndex: 'trigger_timestamp',
},
{
title: '操作',
align: 'center',
render: (dom, entity) => {
return <>
{entity.status === 'COMPLETED' ?
<Button disabled title="暂不可用" onClick={() => recoveryCheckPoint(entity)}>此处恢复</Button> : undefined}
</>
},
},
];
return (
<>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
<ProTable<CheckPointsDetailInfo>
columns={columns}
style={{width: '100%'}}
dataSource={checkPointsList}
onDataSourceChange={(dataSource) => {
actionRef.current?.reload();
}}
actionRef={actionRef}
rowKey="id"
pagination={{
pageSize: 10,
}}
toolBarRender={false}
dateFormatter="string"
search={false}
size="small"
/>
</>
)
}
......@@ -164,46 +283,46 @@ const CheckPoints = (props: any) => {
return (
<>
{(job?.jobHistory?.checkpointsConfig) ?
<Descriptions bordered size="small" column={1} >
<Descriptions bordered size="small" column={1}>
<Descriptions.Item label="Checkpointing Mode">
<Tag color="blue" title={"Checkpointing Mode"}>
{job?.jobHistory?.checkpointsConfig['mode'].toUpperCase() }
{job?.jobHistory?.checkpointsConfig['mode'].toUpperCase()}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Checkpoint Storage">
<Tag color="blue" title={"Checkpoint Storage"}>
{job?.jobHistory?.checkpointsConfig['checkpoint_storage']? job?.jobHistory?.checkpointsConfig['checkpoint_storage'] : 'Disabled'}
{job?.jobHistory?.checkpointsConfig['checkpoint_storage'] ? job?.jobHistory?.checkpointsConfig['checkpoint_storage'] : 'Disabled'}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="State Backend">
<Tag color="blue" title={"State Backend"}>
{job?.jobHistory?.checkpointsConfig['state_backend'] ? job?.jobHistory?.checkpointsConfig['state_backend'] : 'Disabled' }
{job?.jobHistory?.checkpointsConfig['state_backend'] ? job?.jobHistory?.checkpointsConfig['state_backend'] : 'Disabled'}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Interval">
<Tag color="blue" title={"Interval"}>
{job?.jobHistory?.checkpointsConfig['interval'] }
{job?.jobHistory?.checkpointsConfig['interval']}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Timeout">
<Tag color="blue" title={"Timeout"}>
{parseMilliSecondStr(job?.jobHistory?.checkpointsConfig['timeout'])}
{(job?.jobHistory?.checkpointsConfig['timeout'])}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Minimum Pause Between Checkpoints">
<Tag color="blue" title={"Minimum Pause Between Checkpoints"}>
{parseSecondStr(job?.jobHistory?.checkpointsConfig['min_pause']) }
{(job?.jobHistory?.checkpointsConfig['min_pause'])}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Maximum Concurrent Checkpoints">
<Tag color="blue" title={"Maximum Concurrent Checkpoints"}>
{job?.jobHistory?.checkpointsConfig['max_concurrent'] }
{job?.jobHistory?.checkpointsConfig['max_concurrent']}
</Tag>
</Descriptions.Item>
......@@ -229,7 +348,7 @@ const CheckPoints = (props: any) => {
<Descriptions.Item label="Tolerable Failed Checkpoints">
<Tag color="blue" title={"Tolerable Failed Checkpoints"}>
{job?.jobHistory?.checkpointsConfig['tolerable_failed_checkpoints'] }
{job?.jobHistory?.checkpointsConfig['tolerable_failed_checkpoints']}
</Tag>
</Descriptions.Item>
</Descriptions>
......
......@@ -114,3 +114,14 @@ export type TaskContainerConfigInfo = {
}
export type CheckPointsDetailInfo = {
jobID: number,
historyID: number,
id: number,
status: string,
end_to_end_duration: number,
external_path : string,
latest_ack_timestamp: number,
state_size: number,
trigger_timestamp: number,
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment