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)
}
];
}