From c438c3fd0b0a9dabd29a3fd2da28efdd0286c3ec Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Wed, 23 Aug 2023 18:24:36 +0800 Subject: [PATCH] perf: gpu quota --- .../public/locales/en/common.json | 7 ++ .../src/components/Icon/icons/log.svg | 7 +- .../src/pages/api/platform/resourcePrice.ts | 6 +- .../pages/app/edit/components/QuotaBox.tsx | 2 +- .../applaunchpad/src/pages/app/edit/index.tsx | 118 +++++++++--------- .../src/services/backend/kubernetes.ts | 4 +- 6 files changed, 80 insertions(+), 64 deletions(-) diff --git a/frontend/providers/applaunchpad/public/locales/en/common.json b/frontend/providers/applaunchpad/public/locales/en/common.json index 04d25b51596a..f13f89cfe4e7 100644 --- a/frontend/providers/applaunchpad/public/locales/en/common.json +++ b/frontend/providers/applaunchpad/public/locales/en/common.json @@ -145,6 +145,9 @@ "Gpu under inventory Tip": "{{gputype}} is out of stock, please change the model or amount", "app": { "Resource Quota": "Quota", + "The applied CPU exceeds the quota": "The applied CPU exceeds the quota", + "The applied memory exceeds the quota": "The applied memory exceeds the quota", + "The applied GPU exceeds the quota": "The applied GPU exceeds the quota", "The applied storage exceeds the quota": "The applied storage exceeds the quota", "The container exposed port cannot be empty": "The container exposed port cannot be empty", "The minimum exposed port is 1": "The minimum exposed port is 1", @@ -152,5 +155,9 @@ }, "user": { "Insufficient account balance": "Insufficient account balance" + }, + "common": { + "Used": "Used", + "Surplus": "Surplus" } } diff --git a/frontend/providers/applaunchpad/src/components/Icon/icons/log.svg b/frontend/providers/applaunchpad/src/components/Icon/icons/log.svg index 7dedd37e59c6..9140c6fb531a 100644 --- a/frontend/providers/applaunchpad/src/components/Icon/icons/log.svg +++ b/frontend/providers/applaunchpad/src/components/Icon/icons/log.svg @@ -1 +1,6 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/frontend/providers/applaunchpad/src/pages/api/platform/resourcePrice.ts b/frontend/providers/applaunchpad/src/pages/api/platform/resourcePrice.ts index e4779509681d..fb372ba76b79 100644 --- a/frontend/providers/applaunchpad/src/pages/api/platform/resourcePrice.ts +++ b/frontend/providers/applaunchpad/src/pages/api/platform/resourcePrice.ts @@ -119,8 +119,9 @@ async function getGpuNode({ k8sCore }: { k8sCore: CoreV1Api }) { try { const { body } = await k8sCore.readNamespacedConfigMap(gpuCrName, gpuCrNS); const gpuMap = body?.data?.gpu; - const alias = (body?.data?.alias || {}) as Record; - if (!gpuMap) return []; + if (!gpuMap || !body?.data?.alias) return []; + const alias = (JSON.parse(body?.data?.alias) || {}) as Record; + const parseGpuMap = JSON.parse(gpuMap) as Record< string, { @@ -129,6 +130,7 @@ async function getGpuNode({ k8sCore }: { k8sCore: CoreV1Api }) { 'gpu.product': string; } >; + const gpuValues = Object.values(parseGpuMap).filter((item) => item['gpu.product']); const gpuList: GpuNodeType[] = []; diff --git a/frontend/providers/applaunchpad/src/pages/app/edit/components/QuotaBox.tsx b/frontend/providers/applaunchpad/src/pages/app/edit/components/QuotaBox.tsx index 231fe17f9f09..8fa0ced5f084 100644 --- a/frontend/providers/applaunchpad/src/pages/app/edit/components/QuotaBox.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/edit/components/QuotaBox.tsx @@ -20,7 +20,7 @@ const sourceMap = { }, gpu: { color: '#89CD11', - unit: 'G' + unit: 'Card' } }; diff --git a/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx b/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx index 29f88410f822..f8275467398a 100644 --- a/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx +++ b/frontend/providers/applaunchpad/src/pages/app/edit/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useMemo, useRef } from 'react'; +import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react'; import { useRouter } from 'next/router'; import { Flex, Box } from '@chakra-ui/react'; import type { YamlItemType } from '@/types'; @@ -12,7 +12,6 @@ import { } from '@/utils/deployYaml2Json'; import { useForm } from 'react-hook-form'; import { defaultEditVal, editModeMap } from '@/constants/editApp'; -import debounce from 'lodash/debounce'; import { postDeployApp, putApp } from '@/api/app'; import { useConfirm } from '@/hooks/useConfirm'; import type { AppEditType, DeployKindsType } from '@/types/app'; @@ -120,21 +119,12 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) => const formHook = useForm({ defaultValues: defaultEditVal }); + const realTimeForm = useRef(defaultEditVal); - // eslint-disable-next-line react-hooks/exhaustive-deps - const formOnchangeDebounce = useCallback( - debounce((data: AppEditType) => { - try { - setYamlList(formData2Yamls(data)); - } catch (error) { - console.log(error); - } - }, 200), - [] - ); // watch form change, compute new yaml formHook.watch((data) => { - data && formOnchangeDebounce(data as AppEditType); + if (!data) return; + realTimeForm.current = data as AppEditType; setForceUpdate(!forceUpdate); }); @@ -153,54 +143,56 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) => [defaultGpuSource?.amount, defaultGpuSource?.type, userSourcePrice?.gpu] ); - const submitSuccess = useCallback(async () => { - setIsLoading(true); - try { - const yamls = yamlList.map((item) => item.value); + const submitSuccess = useCallback( + async (yamlList: YamlItemType[]) => { + setIsLoading(true); + try { + const yamls = yamlList.map((item) => item.value); - if (appName) { - const patch = patchYamlList({ - formOldYamlList: formOldYamls.current.map((item) => item.value), - crYamlList: crOldYamls.current, - newYamlList: yamls - }); + if (appName) { + const patch = patchYamlList({ + formOldYamlList: formOldYamls.current.map((item) => item.value), + crYamlList: crOldYamls.current, + newYamlList: yamls + }); - await putApp({ - patch, - appName, - stateFulSetYaml: yamlList.find((item) => item.filename === 'statefulSet.yaml')?.value - }); - } else { - await postDeployApp(yamls); - } + await putApp({ + patch, + appName, + stateFulSetYaml: yamlList.find((item) => item.filename === 'statefulSet.yaml')?.value + }); + } else { + await postDeployApp(yamls); + } - router.replace(`/app/detail?name=${formHook.getValues('appName')}`); - toast({ - title: t(applySuccess), - status: 'success' - }); + router.replace(`/app/detail?name=${formHook.getValues('appName')}`); + toast({ + title: t(applySuccess), + status: 'success' + }); - if (userSourcePrice?.gpu) { - refetchPrice(); + if (userSourcePrice?.gpu) { + refetchPrice(); + } + } catch (error) { + console.error(error); + const msg = getErrText(error); + setErrorMessage(msg || JSON.stringify(error)); } - } catch (error) { - console.error(error); - const msg = getErrText(error); - setErrorMessage(msg || JSON.stringify(error)); - } - setIsLoading(false); - }, [ - setIsLoading, - toast, - yamlList, - appName, - router, - formHook, - t, - applySuccess, - userSourcePrice?.gpu, - refetchPrice - ]); + setIsLoading(false); + }, + [ + setIsLoading, + toast, + appName, + router, + formHook, + t, + applySuccess, + userSourcePrice?.gpu, + refetchPrice + ] + ); const submitError = useCallback(() => { // deep search message const deepSearch = (obj: any): string => { @@ -269,6 +261,14 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) => } ); + useEffect(() => { + if (tabType === 'yaml' && router.query.name) { + try { + setYamlList(formData2Yamls(realTimeForm.current)); + } catch (error) {} + } + }, [router.query.name, tabType]); + return ( <> applyBtnText={applyBtnText} applyCb={() => formHook.handleSubmit((data) => { + const parseYamls = formData2Yamls(data); + setYamlList(parseYamls); // balance check if (balance <= 0) { return toast({ @@ -315,7 +317,7 @@ const EditApp = ({ appName, tabType }: { appName?: string; tabType: string }) => isClosable: true }); } - openConfirm(submitSuccess)(); + openConfirm(() => submitSuccess(parseYamls))(); }, submitError)() } /> diff --git a/frontend/providers/applaunchpad/src/services/backend/kubernetes.ts b/frontend/providers/applaunchpad/src/services/backend/kubernetes.ts index b59ded81f9bc..494df9e23c7d 100644 --- a/frontend/providers/applaunchpad/src/services/backend/kubernetes.ts +++ b/frontend/providers/applaunchpad/src/services/backend/kubernetes.ts @@ -159,8 +159,8 @@ export async function getUserQuota( }, { type: 'gpu', - limit: Number(status?.hard?.['limits.nvidia.com/gpu'] || 0), - used: Number(status?.used?.['limits.nvidia.com/gpu'] || 0) + limit: Number(status?.hard?.['requests.nvidia.com/gpu'] || 0), + used: Number(status?.used?.['requests.nvidia.com/gpu'] || 0) } ]; }