Skip to content

Commit 07bcc5a

Browse files
committed
feat(FR-1391): Add auto scaling rule
1 parent 1e43668 commit 07bcc5a

File tree

5 files changed

+764
-26
lines changed

5 files changed

+764
-26
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
import QuestionIconWithTooltip from './QuestionIconWithTooltip';
2+
import { DeleteOutlined, SettingOutlined } from '@ant-design/icons';
3+
import { Button, ConfigProvider, Empty, theme, Typography } from 'antd';
4+
import {
5+
BAITable,
6+
filterOutNullAndUndefined,
7+
filterOutEmpty,
8+
BAIColumnType,
9+
BAIFlex,
10+
} from 'backend.ai-ui';
11+
import dayjs from 'dayjs';
12+
import { useTranslation } from 'react-i18next';
13+
import { graphql, useFragment } from 'react-relay';
14+
import {
15+
AutoScalingRuleListFragment$key,
16+
AutoScalingRuleListFragment$data,
17+
} from 'src/__generated__/AutoScalingRuleListFragment.graphql';
18+
import { formatDuration } from 'src/helper';
19+
20+
export type AutoScalingRuleInList = NonNullable<
21+
AutoScalingRuleListFragment$data[number]
22+
>;
23+
24+
interface AutoScalingRuleListProps {
25+
autoScalingRulesFrgmt?: AutoScalingRuleListFragment$key;
26+
onRequestSettingAutoScalingRule: (record?: AutoScalingRuleInList) => void;
27+
onRequestDelete: (record: AutoScalingRuleInList) => void;
28+
}
29+
30+
const AutoScalingRuleList: React.FC<AutoScalingRuleListProps> = ({
31+
autoScalingRulesFrgmt,
32+
onRequestSettingAutoScalingRule,
33+
onRequestDelete,
34+
}) => {
35+
const { t } = useTranslation();
36+
const { token } = theme.useToken();
37+
38+
const autoScalingRules = useFragment(
39+
graphql`
40+
fragment AutoScalingRuleListFragment on AutoScalingRule
41+
@relay(plural: true) {
42+
id @required(action: THROW)
43+
metricSource
44+
metricName
45+
minThreshold
46+
maxThreshold
47+
stepSize
48+
timeWindow
49+
minReplicas
50+
maxReplicas
51+
createdAt
52+
lastTriggeredAt
53+
}
54+
`,
55+
autoScalingRulesFrgmt,
56+
);
57+
58+
const filteredAutoScalingRules = filterOutNullAndUndefined(autoScalingRules);
59+
60+
const columns = filterOutEmpty<BAIColumnType<AutoScalingRuleInList>>([
61+
{
62+
key: 'metricSource',
63+
dataIndex: 'metricSource',
64+
title: t('deployment.MetricSource'),
65+
fixed: 'left',
66+
render: (metricSource) => (
67+
<Typography.Text>
68+
{metricSource === 'KERNEL' ? 'Kernel' : 'Inference Framework'}
69+
</Typography.Text>
70+
),
71+
},
72+
{
73+
key: 'metricName',
74+
dataIndex: 'metricName',
75+
title: t('deployment.MetricName'),
76+
render: (metricName) => <Typography.Text>{metricName}</Typography.Text>,
77+
},
78+
{
79+
key: 'controls',
80+
title: t('general.Control'),
81+
render: (_, record) => (
82+
<BAIFlex align="stretch">
83+
<Button
84+
type="link"
85+
style={{ color: token.colorInfo }}
86+
icon={<SettingOutlined />}
87+
onClick={() => onRequestSettingAutoScalingRule?.(record)}
88+
/>
89+
<Button
90+
type="link"
91+
style={{ color: token.colorError }}
92+
icon={<DeleteOutlined />}
93+
onClick={() => onRequestDelete?.(record)}
94+
/>
95+
</BAIFlex>
96+
),
97+
},
98+
{
99+
key: 'minThreshold',
100+
dataIndex: 'minThreshold',
101+
title: (
102+
<BAIFlex gap={'xxs'}>
103+
{t('deployment.MinThreshold')}
104+
<QuestionIconWithTooltip title={t('deployment.MinThresholdDesc')} />
105+
</BAIFlex>
106+
),
107+
render: (minThreshold) => (
108+
<Typography.Text>{minThreshold || '-'}</Typography.Text>
109+
),
110+
},
111+
{
112+
key: 'maxThreshold',
113+
dataIndex: 'maxThreshold',
114+
title: (
115+
<BAIFlex gap={'xxs'}>
116+
{t('deployment.MaxThreshold')}
117+
<QuestionIconWithTooltip title={t('deployment.MaxThresholdDesc')} />
118+
</BAIFlex>
119+
),
120+
render: (maxThreshold) => (
121+
<Typography.Text>{maxThreshold || '-'}</Typography.Text>
122+
),
123+
},
124+
{
125+
key: 'stepSize',
126+
dataIndex: 'stepSize',
127+
title: (
128+
<BAIFlex gap={'xxs'}>
129+
{t('deployment.StepSize')}
130+
<QuestionIconWithTooltip title={t('deployment.StepSizeDesc')} />
131+
</BAIFlex>
132+
),
133+
render: (stepSize) => <Typography.Text>{stepSize}</Typography.Text>,
134+
},
135+
{
136+
key: 'timeWindow',
137+
dataIndex: 'timeWindow',
138+
title: (
139+
<BAIFlex gap={'xxs'}>
140+
{t('deployment.TimeWindow')}
141+
<QuestionIconWithTooltip title={t('deployment.TimeWindowDesc')} />
142+
</BAIFlex>
143+
),
144+
render: (timeWindow) => (
145+
<Typography.Text>
146+
{formatDuration(dayjs.duration(Number(timeWindow), 'seconds'), t)}
147+
</Typography.Text>
148+
),
149+
},
150+
{
151+
key: 'minReplicas',
152+
dataIndex: 'minReplicas',
153+
title: (
154+
<BAIFlex gap={'xxs'}>
155+
{t('deployment.MinReplicas')}
156+
<QuestionIconWithTooltip title={t('deployment.MinReplicasDesc')} />
157+
</BAIFlex>
158+
),
159+
render: (minReplicas) => (
160+
<Typography.Text>{minReplicas || '-'}</Typography.Text>
161+
),
162+
},
163+
{
164+
key: 'maxReplicas',
165+
dataIndex: 'maxReplicas',
166+
title: (
167+
<BAIFlex gap={'xxs'}>
168+
{t('deployment.MaxReplicas')}
169+
<QuestionIconWithTooltip title={t('deployment.MaxReplicasDesc')} />
170+
</BAIFlex>
171+
),
172+
render: (maxReplicas) => (
173+
<Typography.Text>{maxReplicas || '-'}</Typography.Text>
174+
),
175+
},
176+
{
177+
key: 'lastTriggeredAt',
178+
dataIndex: 'lastTriggeredAt',
179+
title: t('deployment.LastTriggeredAt'),
180+
render: (lastTriggeredAt) => (
181+
<Typography.Text>
182+
{lastTriggeredAt ? dayjs(lastTriggeredAt).format('LLL') : '-'}
183+
</Typography.Text>
184+
),
185+
},
186+
{
187+
key: 'createdAt',
188+
dataIndex: 'createdAt',
189+
title: t('deployment.CreatedAt'),
190+
render: (createdAt) => (
191+
<Typography.Text>{dayjs(createdAt).format('LLL')}</Typography.Text>
192+
),
193+
},
194+
]);
195+
196+
return (
197+
<ConfigProvider
198+
renderEmpty={() => (
199+
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}>
200+
<Button
201+
type="primary"
202+
onClick={() => onRequestSettingAutoScalingRule()}
203+
>
204+
{t('deployment.SetAutoScalingRule')}
205+
</Button>
206+
</Empty>
207+
)}
208+
>
209+
<BAITable
210+
resizable
211+
columns={columns}
212+
dataSource={filteredAutoScalingRules}
213+
rowKey="id"
214+
size="small"
215+
/>
216+
</ConfigProvider>
217+
);
218+
};
219+
220+
export default AutoScalingRuleList;

0 commit comments

Comments
 (0)