Skip to content

Commit

Permalink
perf: launchpad request controller
Browse files Browse the repository at this point in the history
  • Loading branch information
c121914yu committed Jul 13, 2023
1 parent f6692ac commit f7188d1
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 69 deletions.
3 changes: 0 additions & 3 deletions frontend/providers/applaunchpad/src/api/platform.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import { GET, POST, DELETE } from '@/services/request';
import type { ServiceEnvType } from '@/types';
import type { Response as resourcePriceResponse } from '@/pages/api/platform/resourcePrice';

export const getEnvs = () => GET<ServiceEnvType>('/api/platform/getEnv');

export const getResourcePrice = () => GET<resourcePriceResponse>('/api/platform/resourcePrice');
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ interface Props extends BoxProps {
render?: (item: any) => JSX.Element;
}[];
data: any[];
itemClass?: string;
}

const Table = ({ columns, data }: Props) => {
const Table = ({ columns, data, itemClass = '' }: Props) => {
const { t } = useTranslation();
return (
<Grid templateColumns={`repeat(${columns.length},1fr)`} overflowX={'auto'}>
Expand All @@ -39,6 +40,8 @@ const Table = ({ columns, data }: Props) => {
{data.map((item: any, index1) =>
columns.map((col, index2) => (
<Flex
className={index2 === 0 ? itemClass : ''}
data-id={item.id}
key={col.key}
alignItems={'center'}
bg={'white'}
Expand Down
29 changes: 12 additions & 17 deletions frontend/providers/applaunchpad/src/mock/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,10 @@ export const MOCK_APP_DETAIL: AppDetailType = {
createTime: '2022/1/22',
status: appStatusMap.waiting,
isPause: false,
appName: 'appname',
imageName: 'dafdsa/asdfad:asdfsda',
runCMD: 'dafda',
cmdParam: 'daf das',
appName: 'appName',
imageName: 'nginx',
runCMD: '',
cmdParam: '',
replicas: 5,
cpu: 1,
memory: 1,
Expand All @@ -299,28 +299,23 @@ export const MOCK_APP_DETAIL: AppDetailType = {
accessExternal: {
use: true,
backendProtocol: 'HTTP',
outDomain: 'sadfsdaf',
selfDomain: 'dafsd'
outDomain: '',
selfDomain: ''
},
envs: [{ key: 'adsfda', value: 'sfaasd' }],
envs: [],
hpa: {
use: true,
use: false,
target: 'cpu',
value: 50,
minReplicas: 3,
maxReplicas: 10
minReplicas: 1,
maxReplicas: 1
},
configMapList: [
{
mountPath: 'string',
value: ''
}
],
configMapList: [],
secret: {
use: true,
username: 'string',
password: 'string',
serverAddress: 'string'
},
storeList: [{ name: 'vn-data', path: '/data', value: 2 }]
storeList: []
};
21 changes: 18 additions & 3 deletions frontend/providers/applaunchpad/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useConfirm } from '@/hooks/useConfirm';
import throttle from 'lodash/throttle';
import { useGlobalStore } from '@/store/global';
import { useLoading } from '@/hooks/useLoading';
import { getServiceEnv, getUserPrice, SEALOS_DOMAIN } from '@/store/static';
import { setServiceEnv, getUserPrice } from '@/store/static';
import { useRouter } from 'next/router';
import { appWithTranslation, useTranslation } from 'next-i18next';
import { getLangStore, setLangStore } from '@/utils/cookieUtils';
Expand All @@ -36,7 +36,12 @@ const queryClient = new QueryClient({
}
});

const App = ({ Component, pageProps }: AppProps) => {
const App = ({
Component,
pageProps,
SEALOS_DOMAIN,
INGRESS_SECRET
}: AppProps & { SEALOS_DOMAIN: string; INGRESS_SECRET: string }) => {
const router = useRouter();
const { i18n } = useTranslation();
const { setScreenWidth, loading, setLastRoute } = useGlobalStore();
Expand All @@ -50,7 +55,10 @@ const App = ({ Component, pageProps }: AppProps) => {
useEffect(() => {
NProgress.start();

getServiceEnv();
setServiceEnv({
SEALOS_DOMAIN,
INGRESS_SECRET
});
getUserPrice();
const response = createSealosApp();

Expand Down Expand Up @@ -147,4 +155,11 @@ const App = ({ Component, pageProps }: AppProps) => {
);
};

App.getInitialProps = async () => {
return {
SEALOS_DOMAIN: process.env.SEALOS_DOMAIN || 'cloud.sealos.io',
INGRESS_SECRET: process.env.INGRESS_SECRET || 'wildcard-cert'
};
};

export default appWithTranslation(App);
19 changes: 0 additions & 19 deletions frontend/providers/applaunchpad/src/pages/api/platform/getEnv.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)

function countSourcePrice(rawData: PriceCrdType, type: ResourceType) {
const rawPrice =
rawData?.status?.billingRecords.find((item) => item.resourceType === type)?.price || 1;
rawData?.status?.billingRecords?.find((item) => item.resourceType === type)?.price || 1;
const sourceScale = rawPrice * (valuationMap[type] || 1);
const unitScale = sourceScale / PRICE_SCALE;
return unitScale;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ const Pods = ({
];

return (
<Box h={'100%'} py={5}>
<Box h={'100%'} py={5} position={'relative'}>
<Flex px={6} alignItems={'center'}>
<MyIcon name="podList" w={'14px'} color={'myGray.500'} />
<Box ml={3} flex={1} color={'myGray.600'}>
Expand Down Expand Up @@ -249,6 +249,7 @@ const Pods = ({
</Tbody>
</Table>
</TableContainer>

<Loading loading={loading} fixed={false} />
{logsPodIndex !== undefined && (
<LogsModal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const AppDetail = ({ appName }: { appName: string }) => {

// interval get pods metrics
useQuery(
['intervalLoadPods'],
['app-detail-pod'],
() => {
if (appDetail?.isPause) return null;
return intervalLoadPods(appName, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ const AppList = ({
]);

return (
<Box backgroundColor={'#F3F4F5'} px={'34px'} minH="100vh">
<Box backgroundColor={'#F3F4F5'} px={'34px'} pb={5} minH={'100%'}>
<Flex h={'88px'} alignItems={'center'}>
<Box mr={4} p={2} backgroundColor={'#FEFEFE'} border={theme.borders.sm} borderRadius={'sm'}>
<MyIcon name="logo" w={'24px'} h={'24px'} />
Expand All @@ -285,7 +285,7 @@ const AppList = ({
{t('Create Application')}
</Button>
</Flex>
<MyTable columns={columns.current} data={apps} />
<MyTable itemClass="appItem" columns={columns.current} data={apps} />
<PauseChild />
{!!delAppName && (
<DelModal appName={delAppName} onClose={() => setDelAppName('')} onSuccess={refetchApps} />
Expand Down
35 changes: 28 additions & 7 deletions frontend/providers/applaunchpad/src/pages/apps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { serviceSideProps } from '@/utils/i18n';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import { useCallback, useEffect, useRef, useState } from 'react';

import { RequestController, isElementInViewport } from '@/utils/tools';
import AppList from './components/appList';
import Empty from './components/empty';

Expand All @@ -31,15 +33,30 @@ const Home = () => {
}
});

const requestController = useRef(new RequestController());

useQuery(
['intervalLoadPods', appList.length],
() =>
Promise.allSettled(
appList.map((app) => {
if (app.isPause) return null;
return intervalLoadPods(app.name, false);
})
),
() => {
const doms = document.querySelectorAll(`.appItem`);
const viewportDomIds = Array.from(doms)
.filter((item) => isElementInViewport(item))
.map((item) => item.getAttribute('data-id'));

const viewportApps =
viewportDomIds.length < 3
? appList
: appList.filter((app) => viewportDomIds.includes(app.id));

return requestController.current.runTasks({
tasks: viewportApps
.filter((app) => !app.isPause)
.map((app) => {
return () => intervalLoadPods(app.name, false);
}),
limit: 3
});
},
{
refetchOnMount: true,
refetchInterval: 3000,
Expand All @@ -63,6 +80,10 @@ const Home = () => {
useEffect(() => {
router.prefetch('/app/detail');
router.prefetch('/app/edit');

return () => {
requestController.current?.stop();
};
}, [router]);

return (
Expand Down
7 changes: 5 additions & 2 deletions frontend/providers/applaunchpad/src/store/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export const useAppStore = create<State>()(
},
setAppDetail: async (appName: string) => {
set((state) => {
state.appDetail = undefined;
state.appDetail = {
...MOCK_APP_DETAIL,
appName
};
state.appDetailPods = [];
});
const res = await getAppByName(appName);
Expand Down Expand Up @@ -124,7 +127,7 @@ export const useAppStore = create<State>()(
item.name === appName ? [...item.useMemory.slice(1), aveMemory] : item.useMemory
}));
});
return null;
return 'success';
}
}))
)
Expand Down
20 changes: 8 additions & 12 deletions frontend/providers/applaunchpad/src/store/static.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { getEnvs, getResourcePrice } from '@/api/platform';
import { getResourcePrice } from '@/api/platform';
import type { Response as resourcePriceResponse } from '@/pages/api/platform/resourcePrice';
import { ServiceEnvType } from '@/types';

export let SEALOS_DOMAIN = 'cloud.sealos.io';
export let INGRESS_SECRET = 'wildcard-cert';

export const setServiceEnv = (res: ServiceEnvType) => {
SEALOS_DOMAIN = res.SEALOS_DOMAIN;
INGRESS_SECRET = res.INGRESS_SECRET;
};

export let SOURCE_PRICE: resourcePriceResponse = {
cpu: 0.067,
memory: 0.033792,
Expand All @@ -11,17 +18,6 @@ export let SOURCE_PRICE: resourcePriceResponse = {
export let INSTALL_ACCOUNT = false;

let retryGetPrice = 3;

export const getServiceEnv = async () => {
try {
const res = await getEnvs();
SEALOS_DOMAIN = res.SEALOS_DOMAIN;
INGRESS_SECRET = res.INGRESS_SECRET;
} catch (err) {
console.log(err);
}
};

export const getUserPrice = async () => {
try {
const res = await getResourcePrice();
Expand Down
53 changes: 53 additions & 0 deletions frontend/providers/applaunchpad/src/utils/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,56 @@ export const patchYamlList = (oldYamlList: string[], newYamlList: string[]) => {

return actions;
};

/* request number limit */
export class RequestController {
results: any[] = [];
index = 0;
runNum = 0;

tasks: (() => any)[] = [];
limit = 3;

async executeTask(index: number): Promise<any> {
const task = this.tasks[index];

if (!task) return;
this.index++;
this.runNum++;
try {
const result = await task();
this.results[index] = result;
} catch (error) {
this.results[index] = error;
}
this.runNum--;
return this.executeTask(this.index);
}

stop() {
this.index = this.tasks.length + 1;
this.tasks = [];
this.runNum = this.limit;
}

async runTasks({ tasks, limit }: { tasks: (() => any)[]; limit: number }) {
this.tasks = tasks;
this.limit = limit;
this.index = 0;
this.runNum = 0;

const arr = new Array(limit).fill(0);
await Promise.allSettled(arr.map((_, i) => this.executeTask(i)));

return this.results;
}
}

export const isElementInViewport = (element: Element) => {
const rect = element.getBoundingClientRect();
const windowHeight = window.innerHeight || document.documentElement.clientHeight;
const windowWidth = window.innerWidth || document.documentElement.clientWidth;
const vertInView = rect.top <= windowHeight && rect.top + rect.height >= 0;
const horInView = rect.left <= windowWidth && rect.left + rect.width >= 0;
return vertInView && horInView;
};

0 comments on commit f7188d1

Please sign in to comment.