From e6f95089005b12f367ff8288f2a12a1b68a6d286 Mon Sep 17 00:00:00 2001 From: ZackYoung Date: Mon, 18 Nov 2024 17:24:55 +0800 Subject: [PATCH] [Refactor][Web]Refactor result query (#3920) Co-authored-by: zackyoungh --- .../org/dinky/controller/TaskController.java | 3 +- .../dinky/data/model/SystemConfiguration.java | 1 + .../SqlTask/TaskConfig/index.tsx | 43 +---- .../CenterTabContent/SqlTask/index.tsx | 39 +++- .../DataStudio/CenterTabContent/index.less | 14 ++ .../Toolbar/Service/Result/index.tsx | 171 ++++++++---------- .../DataStudio/Toolbar/Service/index.tsx | 6 +- .../src/pages/DataStudio/Toolbar/index.tsx | 10 +- dinky-web/src/pages/DataStudio/type.ts | 1 + 9 files changed, 134 insertions(+), 154 deletions(-) diff --git a/dinky-admin/src/main/java/org/dinky/controller/TaskController.java b/dinky-admin/src/main/java/org/dinky/controller/TaskController.java index 79e1563433..a4ecc6c031 100644 --- a/dinky-admin/src/main/java/org/dinky/controller/TaskController.java +++ b/dinky-admin/src/main/java/org/dinky/controller/TaskController.java @@ -178,8 +178,7 @@ public Result> explainSql(@RequestBody TaskDTO taskDTO) t @ExecuteProcess(type = ProcessType.FLINK_JOB_PLAN) @CheckTaskOwner(checkParam = TaskId.class, checkInterface = TaskService.class) public Result getJobPlan(@RequestBody TaskDTO taskDTO) { - ObjectNode jobPlan = null; - jobPlan = taskService.getJobPlan(taskDTO); + ObjectNode jobPlan = taskService.getJobPlan(taskDTO); return Result.succeed(jobPlan, Status.EXECUTE_SUCCESS); } diff --git a/dinky-common/src/main/java/org/dinky/data/model/SystemConfiguration.java b/dinky-common/src/main/java/org/dinky/data/model/SystemConfiguration.java index 539ca363a0..5ef4aa6c84 100644 --- a/dinky-common/src/main/java/org/dinky/data/model/SystemConfiguration.java +++ b/dinky-common/src/main/java/org/dinky/data/model/SystemConfiguration.java @@ -447,6 +447,7 @@ public Map getFlinkHistoryServerConfiguration() { FileUtil.file(DirConstant.getTempRootDir(), "flink-job-archive") .getAbsolutePath()); config.put("historyserver.archive.fs.dir", FLINK_JOB_ARCHIVE); + config.put("historyserver.archive.clean-expired-jobs", "true"); } return config; } diff --git a/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/TaskConfig/index.tsx b/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/TaskConfig/index.tsx index 560ee2e5e1..fb7b02c581 100644 --- a/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/TaskConfig/index.tsx +++ b/dinky-web/src/pages/DataStudio/CenterTabContent/SqlTask/TaskConfig/index.tsx @@ -17,14 +17,8 @@ * */ -import { Tabs, TabsProps, Tag } from 'antd'; -import { - ProForm, - ProFormDigit, - ProFormGroup, - ProFormSelect, - ProFormSwitch -} from '@ant-design/pro-components'; +import { Tabs, TabsProps } from 'antd'; +import { ProForm, ProFormDigit, ProFormGroup, ProFormSwitch } from '@ant-design/pro-components'; import { l } from '@/utils/intl'; import React from 'react'; import { InfoCircleOutlined } from '@ant-design/icons'; @@ -32,8 +26,6 @@ import { DIALECT, SWITCH_OPTIONS } from '@/services/constants'; import { TaskState, TempData } from '@/pages/DataStudio/type'; import { BasicConfig } from '@/pages/DataStudio/CenterTabContent/SqlTask/TaskConfig/BasicConfig'; import { isSql, assert } from '@/pages/DataStudio/utils'; -import { DataSources } from '@/types/RegCenter/data'; -import { TagAlignLeft } from '@/components/StyledComponents'; import { JOB_LIFE_CYCLE } from '@/pages/DevOps/constants'; export default (props: { @@ -51,7 +43,7 @@ export default (props: { label: l('menu.datastudio.task.baseConfig'), children: ( { - if (isSql(data.dialect)) { - // const dataSourceData: Record = {}; - // const databaseDataList = tempData.dataSourceDataList; - // databaseDataList - // .filter((x) => x.type.toLowerCase() === data?.dialect.toLowerCase()) - // .forEach((item: DataSources.DataSource) => { - // dataSourceData[item.id] = ( - // - // - // {item.type} - // - // {item.name} - // - // ); - // }); - // return ( - // String(value)} - // valueEnum={dataSourceData} - // placeholder='Please select a dataSource' - // rules={[{ required: true, message: 'Please select your dataSource!' }]} - // allowClear={false} - // /> - // ); - } else { + if (!isSql(data.dialect)) { return ( <> { showDesc, tempData, updateAction, - updateProject, updateCenterTab, activeTab, enabledDs, @@ -137,7 +134,8 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { versionId: 0, createTime: new Date(), updateTime: new Date(), - status: '' + status: '', + mockSinkFunction: true }); // 代码恢复 const [openDiffModal, setOpenDiffModal] = useState(false); @@ -146,13 +144,20 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { const formRef = useRef(); const [isFullscreen, { enterFullscreen, exitFullscreen }] = useFullscreen(containerRef); - const { initialState, setInitialState } = useModel('@@initialState'); + const { initialState } = useModel('@@initialState'); + const [refreshTaskStatusDelay, setRefreshTaskStatusDelay] = useState( + undefined + ); + useRafInterval(async () => { + const taskDetail = (await getTaskDetails(params.taskId))!!; + setCurrentState((prevState) => ({ ...prevState, status: taskDetail.status })); + }, refreshTaskStatusDelay); useAsyncEffect(async () => { const taskDetail = await getTaskDetails(params.taskId); if (taskDetail) { const statement = params.statement ?? taskDetail.statement; - const newParams = { ...taskDetail, taskId: params.taskId, statement }; + const newParams = { ...taskDetail, taskId: params.taskId, statement, mockSinkFunction: true }; // @ts-ignore setCurrentState(newParams); updateCenterTab({ ...props.tabData, params: newParams }); @@ -170,6 +175,14 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { } setLoading(false); }, []); + // 定时刷新作业状态 + useEffect(() => { + if (isStatusDone(currentState.status)) { + setRefreshTaskStatusDelay(undefined); + } else { + setRefreshTaskStatusDelay(3000); + } + }, [currentState.status]); // 数据初始化 useEffect(() => { @@ -197,7 +210,6 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { editorInstance.current = editor; // @ts-ignore editor['id'] = currentState.taskId; - editor.onDidChangeCursorPosition((e) => {}); registerEditorKeyBindingAndAction(editor); }; @@ -408,15 +420,22 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { }, [updateAction, currentState.envId, handleSave, currentState.taskId, currentState.dialect]); const handleDebug = useCallback(async () => { + updateAction({ + actionType: DataStudioActionType.TASK_RUN_DEBUG, + params: { + taskId: params.taskId + } + }); const res = await debugTask( l('pages.datastudio.editor.debugging', '', { jobName: currentState.name }), { ...currentState } ); if (res?.success && res?.data?.result?.success) { updateAction({ - actionType: DataStudioActionType.TASK_RUN_DEBUG, + actionType: DataStudioActionType.TASK_PREVIEW_RESULT, params: { taskId: params.taskId, + isMockSinkResult: res.data?.result?.mockSinkResult, columns: res.data?.result?.columns ?? [], rowData: res.data?.result?.rowData ?? [] } @@ -436,7 +455,7 @@ export const SqlTask = memo((props: FlinkSqlProps & any) => { }, [currentState, updateAction]); const handleStop = useCallback(async () => { - const result = await cancelTask('', currentState.taskId, false); + await cancelTask('', currentState.taskId, false); setCurrentState((prevState) => { return { ...prevState, diff --git a/dinky-web/src/pages/DataStudio/CenterTabContent/index.less b/dinky-web/src/pages/DataStudio/CenterTabContent/index.less index 627d05298b..63e34a5dfd 100644 --- a/dinky-web/src/pages/DataStudio/CenterTabContent/index.less +++ b/dinky-web/src/pages/DataStudio/CenterTabContent/index.less @@ -44,3 +44,17 @@ padding: 5px 15px; background-color: var(--main-background-color); } + +.no_diff_content { + display: flex; + align-items: center; + justify-content: center; + height: 50vh; + text-align: center; +} + +.diff_content { + height: 50vh; + padding: 10px; + border: 1px solid #fdfdfd1f; +} diff --git a/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx b/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx index e8db87f9fb..54a505d851 100644 --- a/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx +++ b/dinky-web/src/pages/DataStudio/Toolbar/Service/Result/index.tsx @@ -21,15 +21,10 @@ import { handleGetOption, handleGetOptionWithoutMsg } from '@/services/BusinessC import { API_CONSTANTS } from '@/services/endpoints'; import { transformTableDataToCsv } from '@/utils/function'; import { l } from '@/utils/intl'; -import { - DownloadOutlined, - QuestionCircleOutlined, - SearchOutlined, - SyncOutlined -} from '@ant-design/icons'; +import { DownloadOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons'; import { Highlight } from '@ant-design/pro-layout/es/components/Help/Search'; -import { Button, Empty, Flex, Input, InputRef, Modal, Space, Table, Tabs, Tooltip } from 'antd'; -import { ColumnsType, ColumnType } from 'antd/es/table'; +import { Button, Drawer, Empty, Input, InputRef, Space, Tabs, TabsProps } from 'antd'; +import { ColumnType } from 'antd/es/table'; import { FilterConfirmProps } from 'antd/es/table/interface'; import { DataIndex } from 'rc-table/es/interface'; import React, { useCallback, useEffect, useRef, useState, useTransition } from 'react'; @@ -39,12 +34,13 @@ import { isSql } from '@/pages/DataStudio/utils'; import { ProTable } from '@ant-design/pro-components'; import { getInsights } from '@antv/ava'; import { InsightCard } from '@antv/ava-react'; -import type { InsightsResult } from '@antv/ava/lib/insight/types'; +import type { Datum, InsightsResult } from '@antv/ava/lib/insight/types'; +import { ProColumns } from '@ant-design/pro-table/es/typing'; type Data = { [c: string]: any; - columns?: string[]; - rowData?: object[]; + columns: string[]; + rowData: object[]; }; type DataList = Data[]; export default (props: { taskId: number; action: any; dialect: string }) => { @@ -54,7 +50,6 @@ export default (props: { taskId: number; action: any; dialect: string }) => { dialect } = props; - const [data, setData] = useState({}); const [dataList, setDataList] = useState([]); const [loading, setLoading] = useState(true); const [openAVA, setOpenAVA] = useState(false); @@ -64,15 +59,13 @@ export default (props: { taskId: number; action: any; dialect: string }) => { const [searchedColumn, setSearchedColumn] = useState(''); const searchInput = useRef(null); useEffect(() => { - if ( - actionType === DataStudioActionType.TASK_PREVIEW_RESULT || - actionType === DataStudioActionType.TASK_RUN_DEBUG - ) { - if (data.mockSinkResult == true) { - setDataList(convertMockResultToList({ columns: params.columns, rowData: params.rowData })); - } else { - setData({ columns: params.columns, rowData: params.rowData }); - } + if (actionType === DataStudioActionType.TASK_PREVIEW_RESULT && taskId === params.taskId) { + setDataList( + covertDataList( + { columns: params.columns, rowData: params.rowData }, + params.isMockSinkResult + ) + ); } }, [props.action]); @@ -94,7 +87,13 @@ export default (props: { taskId: number; action: any; dialect: string }) => { setSearchedColumn(''); } }; - const convertMockResultToList = (data: any): any[] => { + const covertDataList = (data: Data, isMockSinkResult: boolean = false) => { + if (isMockSinkResult) { + return convertMockResultToList(data); + } + return [data]; + }; + const convertMockResultToList = (data: Data): Data[] => { const rowDataResults: any[] = []; // 对于每个MockResult的Column,一个元素代表一个表信息 data.columns.forEach((columnString: string) => { @@ -198,13 +197,8 @@ export default (props: { taskId: number; action: any; dialect: string }) => { ); const data = tableData.data; if (tableData.success && data?.success) { - if (data.mockSinkResult == true) { - setDataList(convertMockResultToList(data)); - } else { - setData(data); - } + setDataList(covertDataList(data, data.mockSinkResult)); } else { - setData({}); setDataList([]); } } @@ -214,7 +208,6 @@ export default (props: { taskId: number; action: any; dialect: string }) => { useAsyncEffect(async () => { if (!isSql(dialect)) { - setData({}); setDataList([]); await loadData(); } else { @@ -230,7 +223,7 @@ export default (props: { taskId: number; action: any; dialect: string }) => { sorter: (a, b) => a[item] - b[item], ...getColumnSearchProps(item) }; - }) as ColumnsType; + }) as ProColumns[]; }; const showDetail = async () => { @@ -250,7 +243,7 @@ export default (props: { taskId: number; action: any; dialect: string }) => { ); }; - const renderDownloadButton = () => { + const renderDownloadButton = (data: Data) => { if (data.columns) { const _utf = '\uFEFF'; const csvDataBlob = new Blob([_utf + transformTableDataToCsv(data.columns!, data.rowData!)], { @@ -261,7 +254,7 @@ export default (props: { taskId: number; action: any; dialect: string }) => { } return undefined; }; - const renderAVA = () => { + const renderAVA = (data: Data) => { return (