From 0072f28db87c6a0bb6d39d225b64ad12db8b3b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=95=85=E6=99=9A?= Date: Wed, 17 Jul 2024 16:52:07 +0800 Subject: [PATCH 01/15] PullRequest: 472 fix: add status and count limit when add and edit DDLTask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge branch 'fix/cloud/202405-osc of git@code.alipay.com:oceanbase/oceanbase-developer-center.git into cloud/202405 https://code.alipay.com/oceanbase/oceanbase-developer-center/pull_requests/472 Signed-off-by: 晓康 * fix: add status and count limit when add and edit DDLTask --- .../Task/AlterDdlTask/CreateModal/index.tsx | 7 +++++-- .../Task/AlterDdlTask/DetailContent/index.tsx | 21 ++++++++++++------- .../component/ThrottleEditableCell/index.tsx | 19 ++++++++++------- .../Task/component/ThrottleFormItem/index.tsx | 5 +++-- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/component/Task/AlterDdlTask/CreateModal/index.tsx b/src/component/Task/AlterDdlTask/CreateModal/index.tsx index b0b98d80f..a334c1995 100644 --- a/src/component/Task/AlterDdlTask/CreateModal/index.tsx +++ b/src/component/Task/AlterDdlTask/CreateModal/index.tsx @@ -25,6 +25,7 @@ import { openTasksPage } from '@/store/helper/page'; import type { ModalStore } from '@/store/modal'; import { useDBSession } from '@/store/sessionManager/hooks'; import { formatMessage } from '@/util/intl'; +import { mbToKb } from '@/util/utils'; import { Alert, Button, @@ -142,7 +143,7 @@ const CreateDDLTaskModal: React.FC = (props) => { rowLimit || dataSizeLimit ? { rowLimit, - dataSizeLimit, + dataSizeLimit: mbToKb(dataSizeLimit), } : null, }; @@ -583,7 +584,9 @@ const CreateDDLTaskModal: React.FC = (props) => { - {settingStore.enableOSCLimiting && } + {settingStore.enableOSCLimiting && ( + + )} diff --git a/src/component/Task/AlterDdlTask/DetailContent/index.tsx b/src/component/Task/AlterDdlTask/DetailContent/index.tsx index 007fa988e..9a87494ee 100644 --- a/src/component/Task/AlterDdlTask/DetailContent/index.tsx +++ b/src/component/Task/AlterDdlTask/DetailContent/index.tsx @@ -20,7 +20,6 @@ import { getTaskExecStrategyMap } from '@/component/Task'; import type { ITaskResult, TaskDetail } from '@/d.ts'; import { TaskExecStrategy } from '@/d.ts'; import { formatMessage } from '@/util/intl'; -import { getFormatDateTime } from '@/util/utils'; import React from 'react'; import { Typography, message } from 'antd'; import { SimpleTextItem } from '../../component/SimpleTextItem'; @@ -29,6 +28,8 @@ import ThrottleEditableCell from '../../component/ThrottleEditableCell'; import { getDataSourceModeConfigByConnectionMode } from '@/common/datasource'; import { updateThrottleConfig } from '@/common/network/task'; import setting from '@/store/setting'; +import { getFormatDateTime, kbToMb, mbToKb } from '@/util/utils'; +import { TaskStatus } from '@/d.ts'; const { Text } = Typography; interface IDDLAlterParamters { @@ -122,7 +123,12 @@ export function getItems( textItems: [React.ReactNode, React.ReactNode, number?][]; sectionRender?: (task: TaskDetail) => void; }[] { - const { parameters, id } = task; + const { parameters, id, status } = task; + const cantBeModified = [ + TaskStatus.EXECUTION_SUCCEEDED, + TaskStatus.EXECUTION_FAILED, + TaskStatus.CANCELLED, + ]?.includes(status); if (!task) { return []; } @@ -149,7 +155,7 @@ export function getItems( const handleDataSizeLimit = async (dataSizeLimit, handleClose) => { const res = await updateThrottleConfig(id, { - dataSizeLimit: dataSizeLimit, + dataSizeLimit: mbToKb(dataSizeLimit), rowLimit: parameters?.rateLimitConfig?.rowLimit, }); if (res) { @@ -165,7 +171,7 @@ export function getItems( const handleRowLimit = async (rowLimit, handleClose) => { const res = await updateThrottleConfig(id, { rowLimit, - dataSizeLimit: parameters?.rateLimitConfig?.dataSizeLimit, + dataSizeLimit: mbToKb(parameters?.rateLimitConfig?.dataSizeLimit), }); if (res) { message.success( @@ -300,11 +306,11 @@ export function getItems( , - 1, ] : null, @@ -319,8 +325,9 @@ export function getItems( suffix="MB/s" min={0} max={setting.maxSingleTaskDataSizeLimit} - defaultValue={parameters?.rateLimitConfig?.dataSizeLimit} + defaultValue={kbToMb(parameters?.rateLimitConfig?.dataSizeLimit)} onOk={handleDataSizeLimit} + readlOnly={cantBeModified} />, 1, diff --git a/src/component/Task/component/ThrottleEditableCell/index.tsx b/src/component/Task/component/ThrottleEditableCell/index.tsx index f4c194304..bfffa8369 100644 --- a/src/component/Task/component/ThrottleEditableCell/index.tsx +++ b/src/component/Task/component/ThrottleEditableCell/index.tsx @@ -25,9 +25,10 @@ interface IProps { min: number; max: number; onOk: (value: number, onClose: () => void) => void; + readlOnly?: boolean; } const ThrottleEditableCell: React.FC = (props) => { - const { defaultValue = 10, min, max, suffix, onOk } = props; + const { defaultValue = 10, min, max, suffix, onOk, readlOnly = false } = props; const [isLmitRowEdit, setIsLmitRowEdit] = useState(false); const [lmitValue, setLmitValue] = useState(Number(defaultValue)); const [status, setStatus] = useState(null); @@ -82,13 +83,15 @@ const ThrottleEditableCell: React.FC = (props) => { {lmitValue} {suffix} - { - setIsLmitRowEdit(true); - }} - > - - + {!readlOnly ? ( + { + setIsLmitRowEdit(true); + }} + > + + + ) : null} )} diff --git a/src/component/Task/component/ThrottleFormItem/index.tsx b/src/component/Task/component/ThrottleFormItem/index.tsx index 74ff8558c..9aeb25316 100644 --- a/src/component/Task/component/ThrottleFormItem/index.tsx +++ b/src/component/Task/component/ThrottleFormItem/index.tsx @@ -24,9 +24,10 @@ interface IProps { rowLimit?: number; dataSizeLimit?: number; }; + maxRow?: number; } const ThrottleFormItem: React.FC = (props) => { - const { initialValue } = props; + const { initialValue, maxRow = setting.maxSingleTaskDataSizeLimit } = props; return ( = (props) => { }, ]} > - + Rows/s From 953473aeeed88ed5ea44e9d109373521e272d3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=95=85=E6=99=9A?= Date: Thu, 18 Jul 2024 09:59:12 +0800 Subject: [PATCH 02/15] PullRequest: 473 fix: update osc max row limit count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge branch 'fix/cloud/202405-oscRowLimit of git@code.alipay.com:oceanbase/oceanbase-developer-center.git into cloud/202405 https://code.alipay.com/oceanbase/oceanbase-developer-center/pull_requests/473 Signed-off-by: 晓康 * fix: update osc max roe limit count --- .../Task/AlterDdlTask/CreateModal/index.tsx | 8 +++++++- .../Task/AlterDdlTask/DetailContent/index.tsx | 5 +++-- .../Task/component/ThrottleFormItem/index.tsx | 13 +++++++++---- src/component/Task/const.ts | 3 +++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/component/Task/AlterDdlTask/CreateModal/index.tsx b/src/component/Task/AlterDdlTask/CreateModal/index.tsx index a334c1995..a5ff28082 100644 --- a/src/component/Task/AlterDdlTask/CreateModal/index.tsx +++ b/src/component/Task/AlterDdlTask/CreateModal/index.tsx @@ -46,6 +46,8 @@ import styles from './index.less'; import ThrottleFormItem from '../../component/ThrottleFormItem'; import { SettingStore } from '@/store/setting'; import { getDataSourceModeConfig } from '@/common/datasource'; +import { OscMaxRowLimit, OscMaxDataSizeLimit } from '../../const'; + interface IProps { modalStore?: ModalStore; settingStore?: SettingStore; @@ -585,7 +587,11 @@ const CreateDDLTaskModal: React.FC = (props) => { {settingStore.enableOSCLimiting && ( - + )} diff --git a/src/component/Task/AlterDdlTask/DetailContent/index.tsx b/src/component/Task/AlterDdlTask/DetailContent/index.tsx index 9a87494ee..7bf315bc0 100644 --- a/src/component/Task/AlterDdlTask/DetailContent/index.tsx +++ b/src/component/Task/AlterDdlTask/DetailContent/index.tsx @@ -30,6 +30,7 @@ import { updateThrottleConfig } from '@/common/network/task'; import setting from '@/store/setting'; import { getFormatDateTime, kbToMb, mbToKb } from '@/util/utils'; import { TaskStatus } from '@/d.ts'; +import { OscMaxRowLimit, OscMaxDataSizeLimit } from '../../const'; const { Text } = Typography; interface IDDLAlterParamters { @@ -306,7 +307,7 @@ export function getItems( = (props) => { - const { initialValue, maxRow = setting.maxSingleTaskDataSizeLimit } = props; + const { + initialValue, + maxRowLimit = setting.maxSingleTaskRowLimit, + maxDataSizeLimit = setting.maxSingleTaskDataSizeLimit, + } = props; return ( = (props) => { }, ]} > - + Rows/s @@ -105,7 +110,7 @@ const ThrottleFormItem: React.FC = (props) => { ]} initialValue={initialValue?.dataSizeLimit} > - + MB/s diff --git a/src/component/Task/const.ts b/src/component/Task/const.ts index eb396e929..2eda4536a 100644 --- a/src/component/Task/const.ts +++ b/src/component/Task/const.ts @@ -87,3 +87,6 @@ export const SubTaskTypeMap = { label: formatMessage({ id: 'src.d.ts.DF449BBC', defaultMessage: '回滚' }), }, }; + +export const OscMaxRowLimit = 10000; +export const OscMaxDataSizeLimit = 1000; From 09c91b0383272c642e099a4fc1d89e00c013eabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=9C=9D=E4=BF=8A?= Date: Mon, 29 Jul 2024 14:07:55 +0800 Subject: [PATCH 03/15] PullRequest: 483 Fixes oceanbase/odc#3023 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge branch 'fix/dev-4.3.1-odc-3023 of git@code.alipay.com:oceanbase/oceanbase-developer-center.git into dev-4.3.1 https://code.alipay.com/oceanbase/oceanbase-developer-center/pull_requests/483 Signed-off-by: 晓康 * Fixes oceanbase/odc#3023 --- .../CreateModal/DatabaseQueue.tsx | 31 +++++++++-------- .../components/Template/EditTemplate.tsx | 34 +++++++++++-------- src/page/Project/Database/index.tsx | 2 +- .../ResourceTree/DatabaseTree/index.tsx | 15 ++++---- src/page/Workspace/context/WorkspaceStore.tsx | 2 +- src/store/datasourceStatus.ts | 4 +-- 6 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx b/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx index 39943241b..61d10df30 100644 --- a/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx +++ b/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx @@ -58,22 +58,25 @@ export const DatabaseQueueSelect: React.FC<{ true, true, ); - setDatabaseOptions( - databaseList?.contents?.map((item) => { - const statusInfo = datasourceStatus.statusMap.get(item?.dataSource?.id); - return { - label: item?.name, - value: item?.id, - environment: item?.environment, - dataSource: item?.dataSource, - existed: item?.existed, - unauthorized: !item?.authorizedPermissionTypes?.includes(DatabasePermissionType.CHANGE), - expired: checkDbExpiredByDataSourceStatus(statusInfo?.status), - }; - }), - ); if (databaseList?.contents?.length) { setDefaultDatasource(databaseList?.contents?.[0]?.dataSource); + await datasourceStatus.asyncUpdateStatus([ + ...new Set(databaseList?.contents?.map((item) => item.dataSource?.id)), + ]); + setDatabaseOptions( + databaseList?.contents?.map((item) => { + const statusInfo = datasourceStatus.statusMap.get(item?.dataSource?.id); + return { + label: item?.name, + value: item?.id, + environment: item?.environment, + dataSource: item?.dataSource, + existed: item?.existed, + unauthorized: !item?.authorizedPermissionTypes?.includes(DatabasePermissionType.CHANGE), + expired: checkDbExpiredByDataSourceStatus(statusInfo?.status), + }; + }), + ); } databaseList?.contents?.forEach((db) => { databaseIdMap.set(db.id, false); diff --git a/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx b/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx index 349ba6e80..da44e33ab 100644 --- a/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx +++ b/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx @@ -50,21 +50,25 @@ const EditTemplate: React.FC<{ true, true, ); - - setDatabaseOptions( - databaseList?.contents?.map((item) => { - const statusInfo = datasourceStatus.statusMap.get(item?.dataSource?.id); - return { - label: item?.name, - value: item?.id, - environment: item?.environment, - dataSource: item?.dataSource, - existed: item?.existed, - unauthorized: !item?.authorizedPermissionTypes?.includes(DatabasePermissionType.CHANGE), - expired: checkDbExpiredByDataSourceStatus(statusInfo?.status), - }; - }), - ); + if (databaseList?.contents?.length) { + await datasourceStatus.asyncUpdateStatus([ + ...new Set(databaseList?.contents?.map((item) => item?.dataSource?.id)), + ]); + setDatabaseOptions( + databaseList?.contents?.map((item) => { + const statusInfo = datasourceStatus.statusMap.get(item?.dataSource?.id); + return { + label: item?.name, + value: item?.id, + environment: item?.environment, + dataSource: item?.dataSource, + existed: item?.existed, + unauthorized: !item?.authorizedPermissionTypes?.includes(DatabasePermissionType.CHANGE), + expired: checkDbExpiredByDataSourceStatus(statusInfo?.status), + }; + }), + ); + } }; const initTemplate = async (templateId: number) => { const response = await detailTemplate(templateId, login?.organizationId?.toString()); diff --git a/src/page/Project/Database/index.tsx b/src/page/Project/Database/index.tsx index e07f924b3..2b9c45a90 100644 --- a/src/page/Project/Database/index.tsx +++ b/src/page/Project/Database/index.tsx @@ -94,7 +94,7 @@ const Database: React.FC = ({ id, modalStore }) => { true, ); if (res) { - datasourceStatus.asyncUpdateStatus(res?.contents?.map((item) => item?.dataSource?.id)); + await datasourceStatus.asyncUpdateStatus(res?.contents?.map((item) => item?.dataSource?.id)); setData(res?.contents); setTotal(res?.page?.totalElements); } diff --git a/src/page/Workspace/SideBar/ResourceTree/DatabaseTree/index.tsx b/src/page/Workspace/SideBar/ResourceTree/DatabaseTree/index.tsx index 0bc34f93e..1617744dc 100644 --- a/src/page/Workspace/SideBar/ResourceTree/DatabaseTree/index.tsx +++ b/src/page/Workspace/SideBar/ResourceTree/DatabaseTree/index.tsx @@ -45,6 +45,14 @@ const DatabaseTree: React.FC = function ({ openSelectPanel }) { async function reloadDatabase() { await reloadDatabaseList(); } + async function handleDatabase() { + setDatabases(databaseList?.filter((item) => !!item?.authorizedPermissionTypes?.length)); + const ids: Set = new Set(); + databaseList.forEach((d) => { + ids.add(d.dataSource?.id); + }); + await datasourceStatus.asyncUpdateStatus(Array.from(ids)); + } useEffect(() => { if (selectDatasourceId || selectProjectId) { @@ -54,12 +62,7 @@ const DatabaseTree: React.FC = function ({ openSelectPanel }) { useEffect(() => { if (databaseList?.length) { - setDatabases(databaseList?.filter((item) => !!item?.authorizedPermissionTypes?.length)); - const ids: Set = new Set(); - databaseList.forEach((d) => { - ids.add(d.dataSource?.id); - }); - datasourceStatus.asyncUpdateStatus(Array.from(ids)); + handleDatabase(); } }, [databaseList]); diff --git a/src/page/Workspace/context/WorkspaceStore.tsx b/src/page/Workspace/context/WorkspaceStore.tsx index 8051ba67e..6036e2862 100644 --- a/src/page/Workspace/context/WorkspaceStore.tsx +++ b/src/page/Workspace/context/WorkspaceStore.tsx @@ -80,7 +80,7 @@ export default function WorkspaceStore({ children }) { const reloadDatasourceList = useCallback(async () => { const data = await fetchDatasource(); setDatasourceList(data?.contents || []); - datasourceStatus.asyncUpdateStatus(data?.contents?.map((a) => a.id)); + await datasourceStatus.asyncUpdateStatus(data?.contents?.map((a) => a.id)); }, []); const reloadProjectList = useCallback(async () => { diff --git a/src/store/datasourceStatus.ts b/src/store/datasourceStatus.ts index 2e9122465..b605832d1 100644 --- a/src/store/datasourceStatus.ts +++ b/src/store/datasourceStatus.ts @@ -68,13 +68,13 @@ export class DataSourceStatusStore { } } - public asyncUpdateStatus(ids: IDatasource['id'][]) { + public async asyncUpdateStatus(ids: IDatasource['id'][]) { ids?.forEach((id) => { this.queue.add(id); }); if (this.status === 'stop') { this.status = 'running'; - this.fetchStatus(); + await this.fetchStatus(); } } From faafa722801c0c3333016ddc60505e9ef96db8c6 Mon Sep 17 00:00:00 2001 From: xiaokang Date: Mon, 29 Jul 2024 14:51:34 +0800 Subject: [PATCH 04/15] fix: add mobx observer --- .../CreateModal/DatabaseQueue.tsx | 21 +++++++++++++----- .../components/Template/EditTemplate.tsx | 22 ++++++++++++++----- src/page/Project/Database/index.tsx | 2 +- .../ResourceTree/DatabaseTree/index.tsx | 2 +- src/page/Workspace/context/WorkspaceStore.tsx | 2 +- src/store/datasourceStatus.ts | 2 +- 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx b/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx index 61d10df30..8a7ba0325 100644 --- a/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx +++ b/src/component/Task/MutipleAsyncTask/CreateModal/DatabaseQueue.tsx @@ -2,7 +2,7 @@ import { IConnection, IConnectionStatus } from '@/d.ts'; import login from '@/store/login'; import { formatMessage } from '@/util/intl'; import { Button, Divider, Form, Space, Timeline, Tooltip } from 'antd'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { DeleteOutlined, DownOutlined, PlusOutlined, UpOutlined } from '@ant-design/icons'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; @@ -14,6 +14,7 @@ import { DatabasePermissionType } from '@/d.ts/database'; import { SelectTemplate, CreateTemplate } from '../components/Template'; import datasourceStatus from '@/store/datasourceStatus'; import styles from './index.less'; +import { observer } from 'mobx-react'; export const checkDbExpiredByDataSourceStatus = (status: IConnectionStatus) => { switch (status) { @@ -34,11 +35,12 @@ export const DatabaseQueueSelect: React.FC<{ rootName: (number | string)[]; multipleDatabaseChangeOpen: boolean; setDefaultDatasource: React.Dispatch>; -}> = ({ rootName, multipleDatabaseChangeOpen, setDefaultDatasource }) => { +}> = observer(({ rootName, multipleDatabaseChangeOpen, setDefaultDatasource }) => { const form = Form.useFormInstance(); + const statusMap = datasourceStatus.statusMap; const projectId = Form.useWatch('projectId', form); const [databaseIdMap, setDatabaseIdMap] = useState>(new Map()); - const [databaseOptions, setDatabaseOptions] = useState([]); + const [_databaseOptions, setDatabaseOptions] = useState([]); const { data, run, @@ -60,7 +62,7 @@ export const DatabaseQueueSelect: React.FC<{ ); if (databaseList?.contents?.length) { setDefaultDatasource(databaseList?.contents?.[0]?.dataSource); - await datasourceStatus.asyncUpdateStatus([ + datasourceStatus.asyncUpdateStatus([ ...new Set(databaseList?.contents?.map((item) => item.dataSource?.id)), ]); setDatabaseOptions( @@ -84,6 +86,15 @@ export const DatabaseQueueSelect: React.FC<{ setDatabaseIdMap(databaseIdMap); }; + const databaseOptions = useMemo(() => { + return _databaseOptions?.map((item) => { + return { + ...item, + expired: checkDbExpiredByDataSourceStatus(statusMap.get(item?.dataSource?.id)?.status), + }; + }); + }, [statusMap, _databaseOptions]); + useEffect(() => { if (multipleDatabaseChangeOpen && projectId) { loadDatabaseList(projectId); @@ -234,7 +245,7 @@ export const DatabaseQueueSelect: React.FC<{ ); -}; +}); const DatabaseQueue: React.FC<{ multipleDatabaseChangeOpen: boolean; diff --git a/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx b/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx index da44e33ab..5642957d1 100644 --- a/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx +++ b/src/component/Task/MutipleAsyncTask/components/Template/EditTemplate.tsx @@ -11,7 +11,7 @@ import login from '@/store/login'; import { DownOutlined, PlusOutlined, UpOutlined, DeleteOutlined } from '@ant-design/icons'; import { useRequest } from 'ahooks'; import { Form, message, Input, Timeline, Space, Divider, Button, Drawer } from 'antd'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { flatArray } from '../../CreateModal/helper'; @@ -19,6 +19,7 @@ import InnerSelecter, { DatabaseOption } from '../../CreateModal/InnerSelecter'; import styles from './index.less'; import datasourceStatus from '@/store/datasourceStatus'; import { checkDbExpiredByDataSourceStatus } from '../../CreateModal/DatabaseQueue'; +import { observer } from 'mobx-react'; const EditTemplate: React.FC<{ open: boolean; @@ -26,11 +27,12 @@ const EditTemplate: React.FC<{ templateId: number; onSuccess?: () => Promise; setOpen: React.Dispatch>; -}> = ({ open, projectId, templateId, setOpen, onSuccess }) => { +}> = observer(({ open, projectId, templateId, setOpen, onSuccess }) => { const [form] = Form.useForm(); + const statusMap = datasourceStatus.statusMap; const orderedDatabaseIds = Form.useWatch(['orders'], form); const [currentTemplate, setCurrentTemplate] = useState