Skip to content

Commit c66f579

Browse files
authored
Merge branch 'main' into astandrik.stash-multipart
2 parents d7ec8da + 0a49720 commit c66f579

File tree

10 files changed

+269
-31
lines changed

10 files changed

+269
-31
lines changed

src/containers/Operations/Operations.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function Operations({database}: OperationsProps) {
2525
const {kind, searchValue, pageSize, pageToken, handleKindChange, handleSearchChange} =
2626
useOperationsQueryParams();
2727

28-
const {data, isFetching, error, refetch} = operationsApi.useGetOperationListQuery(
28+
const {data, isLoading, error, refetch} = operationsApi.useGetOperationListQuery(
2929
{database, kind, page_size: pageSize, page_token: pageToken},
3030
{
3131
pollingInterval: autoRefreshInterval,
@@ -53,13 +53,13 @@ export function Operations({database}: OperationsProps) {
5353
searchValue={searchValue}
5454
entitiesCountCurrent={filteredOperations.length}
5555
entitiesCountTotal={data?.operations?.length}
56-
entitiesLoading={isFetching}
56+
entitiesLoading={isLoading}
5757
handleKindChange={handleKindChange}
5858
handleSearchChange={handleSearchChange}
5959
/>
6060
</TableWithControlsLayout.Controls>
6161
{error ? <ResponseError error={error} /> : null}
62-
<TableWithControlsLayout.Table loading={isFetching} className={b('table')}>
62+
<TableWithControlsLayout.Table loading={isLoading} className={b('table')}>
6363
{data ? (
6464
<ResizeableDataTable
6565
columns={getColumns({database, refreshTable: refetch})}

src/containers/PDiskPage/PDiskPage.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ import './PDiskPage.scss';
3737
const pdiskPageCn = cn('ydb-pdisk-page');
3838

3939
const PDISK_TABS_IDS = {
40-
diskDistribution: 'diskDistribution',
40+
spaceDistribution: 'spaceDistribution',
4141
storage: 'storage',
4242
} as const;
4343

4444
const PDISK_PAGE_TABS = [
4545
{
46-
id: PDISK_TABS_IDS.diskDistribution,
46+
id: PDISK_TABS_IDS.spaceDistribution,
4747
get title() {
48-
return pDiskPageKeyset('disk-distribution');
48+
return pDiskPageKeyset('space-distribution');
4949
},
5050
},
5151
{
@@ -56,7 +56,7 @@ const PDISK_PAGE_TABS = [
5656
},
5757
];
5858

59-
const pDiskTabSchema = z.nativeEnum(PDISK_TABS_IDS).catch(PDISK_TABS_IDS.diskDistribution);
59+
const pDiskTabSchema = z.nativeEnum(PDISK_TABS_IDS).catch(PDISK_TABS_IDS.spaceDistribution);
6060

6161
export function PDiskPage() {
6262
const dispatch = useTypedDispatch();
@@ -237,7 +237,7 @@ export function PDiskPage() {
237237

238238
const renderTabsContent = () => {
239239
switch (pDiskTab) {
240-
case 'diskDistribution': {
240+
case 'spaceDistribution': {
241241
return pDiskData ? (
242242
<div className={pdiskPageCn('disk-distribution')}>
243243
<PDiskSpaceDistribution data={pDiskData} />

src/containers/PDiskPage/i18n/en.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"node": "Node",
55

66
"storage": "Storage",
7-
"disk-distribution": "Disk distribution",
7+
"space-distribution": "Space distribution",
88

99
"empty-slot": "Empty slot",
1010
"log": "Log",

src/containers/Tenant/Diagnostics/Configs/Configs.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const Configs = ({database}: ConfigsProps) => {
9191
const [autoRefreshInterval] = useAutoRefreshInterval();
9292
const {
9393
currentData = [],
94-
isFetching,
94+
isLoading,
9595
error,
9696
} = tenantApi.useGetClusterConfigQuery({database}, {pollingInterval: autoRefreshInterval});
9797

@@ -113,7 +113,7 @@ export const Configs = ({database}: ConfigsProps) => {
113113
placeholder={i18n('search-placeholder')}
114114
/>
115115
</TableWithControlsLayout.Controls>
116-
<TableWithControlsLayout.Table loading={isFetching}>
116+
<TableWithControlsLayout.Table loading={isLoading}>
117117
{error ? (
118118
<ResponseError error={error} />
119119
) : (

src/containers/Tenant/utils/schemaQueryTemplates.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const createExternalTableTemplate = (params?: SchemaQueryParams) => {
128128
};
129129

130130
export const createTopicTemplate = (params?: SchemaQueryParams) => {
131-
const path = params?.relativePath ? `\`${params?.relativePath}\`/my_topic` : '${1:my_topic}';
131+
const path = params?.relativePath ? `\`${params?.relativePath}/my_topic\`` : '${1:my_topic}';
132132
return `-- docs: https://ydb.tech/docs/en/yql/reference/syntax/create-topic
133133
CREATE TOPIC ${path} (
134134
CONSUMER consumer1,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
import type {TPDiskInfoResponse} from '../../../../types/api/pdisk';
2+
import {preparePDiskDataResponse} from '../utils';
3+
4+
describe('preparePDiskDataResponse', () => {
5+
const rawData = {
6+
Whiteboard: {
7+
PDisk: {
8+
PDiskId: 1,
9+
ChangeTime: '1738670321505',
10+
Path: '/ydb_data/pdisk1tmbtrl7c.data',
11+
Guid: '1',
12+
Category: '0',
13+
AvailableSize: '66454552576',
14+
TotalSize: '100000000000',
15+
State: 'Normal',
16+
Device: 'Green',
17+
Realtime: 'Green',
18+
SerialNumber: '',
19+
SystemSize: '2000000000',
20+
LogUsedSize: '2000000000',
21+
LogTotalSize: '60000000000',
22+
EnforcedDynamicSlotSize: '20000000000',
23+
NumActiveSlots: 1,
24+
},
25+
VDisks: [
26+
{
27+
VDiskId: {
28+
GroupID: 2181038081,
29+
GroupGeneration: 1,
30+
Ring: 0,
31+
Domain: 0,
32+
VDisk: 0,
33+
},
34+
ChangeTime: '1738672482849',
35+
PDiskId: 1,
36+
VDiskSlotId: 1001,
37+
Guid: '1',
38+
Kind: '0',
39+
VDiskState: 'OK',
40+
DiskSpace: 'Green',
41+
SatisfactionRank: {
42+
FreshRank: {
43+
Flag: 'Green',
44+
},
45+
LevelRank: {
46+
Flag: 'Green',
47+
},
48+
},
49+
Replicated: true,
50+
ReplicationProgress: 1,
51+
ReplicationSecondsRemaining: 0,
52+
AllocatedSize: '5000000000',
53+
AvailableSize: '20000000000',
54+
HasUnreadableBlobs: false,
55+
IncarnationGuid: '13331041715376219418',
56+
InstanceGuid: '18177015420302975983',
57+
FrontQueues: 'Green',
58+
StoragePoolName: 'dynamic_storage_pool:1',
59+
ReadThroughput: '0',
60+
WriteThroughput: '0',
61+
},
62+
],
63+
},
64+
BSC: {
65+
PDisk: {
66+
Type: 'ROT',
67+
Kind: '0',
68+
Path: '/ydb_data/pdisk1tmbtrl7c.data',
69+
Guid: '1',
70+
BoxId: '1',
71+
SharedWithOs: false,
72+
ReadCentric: false,
73+
AvailableSize: '66454552576',
74+
TotalSize: '68719476736',
75+
StatusV2: 'ACTIVE',
76+
StatusChangeTimestamp: '1737458853219782',
77+
EnforcedDynamicSlotSize: '20000000000',
78+
ExpectedSlotCount: 16,
79+
NumActiveSlots: 1,
80+
Category: '0',
81+
DecommitStatus: 'DECOMMIT_NONE',
82+
State: 'Normal',
83+
},
84+
VDisks: [
85+
{
86+
Key: {
87+
NodeId: 1,
88+
PDiskId: 1,
89+
VSlotId: 0,
90+
},
91+
Info: {
92+
GroupId: 0,
93+
GroupGeneration: 1,
94+
FailRealm: 0,
95+
FailDomain: 0,
96+
VDisk: 0,
97+
AllocatedSize: '1000000000',
98+
AvailableSize: '20000000000',
99+
StatusV2: 'READY',
100+
Kind: 'Default',
101+
DiskSpace: 'Green',
102+
Replicated: true,
103+
State: 'OK',
104+
},
105+
},
106+
],
107+
},
108+
} as unknown as TPDiskInfoResponse;
109+
110+
it('Should correctly retrieve slots', () => {
111+
const preparedData = preparePDiskDataResponse([rawData, {}]);
112+
113+
expect(preparedData.SlotItems?.length).toEqual(17);
114+
expect(preparedData.SlotItems?.filter((slot) => slot.SlotType === 'log').length).toEqual(1);
115+
expect(preparedData.SlotItems?.filter((slot) => slot.SlotType === 'vDisk').length).toEqual(
116+
1,
117+
);
118+
expect(preparedData.SlotItems?.filter((slot) => slot.SlotType === 'empty').length).toEqual(
119+
15,
120+
);
121+
});
122+
it('Should correctly calculate empty slots size if EnforcedDynamicSlotSize is provided', () => {
123+
const preparedData = preparePDiskDataResponse([rawData, {}]);
124+
125+
expect(preparedData.SlotItems?.find((slot) => slot.SlotType === 'empty')?.Total).toEqual(
126+
20_000_000_000,
127+
);
128+
});
129+
it('Should correctly calculate empty slots size if EnforcedDynamicSlotSize is undefined', () => {
130+
const data: TPDiskInfoResponse = {
131+
...rawData,
132+
Whiteboard: {
133+
...rawData.Whiteboard,
134+
PDisk: {
135+
...rawData.Whiteboard?.PDisk,
136+
EnforcedDynamicSlotSize: undefined,
137+
},
138+
},
139+
BSC: {
140+
...rawData.BSC,
141+
PDisk: {
142+
...rawData.BSC?.PDisk,
143+
EnforcedDynamicSlotSize: undefined,
144+
},
145+
},
146+
};
147+
const preparedData = preparePDiskDataResponse([data, {}]);
148+
149+
expect(preparedData.SlotItems?.find((slot) => slot.SlotType === 'empty')?.Total).toEqual(
150+
1_000_000_000,
151+
);
152+
});
153+
it('Should return yellow or red severity for log if its size exceeds thresholds', () => {
154+
const dataWarning: TPDiskInfoResponse = {
155+
...rawData,
156+
Whiteboard: {
157+
...rawData.Whiteboard,
158+
PDisk: {
159+
...rawData.Whiteboard?.PDisk,
160+
LogUsedSize: '90',
161+
LogTotalSize: '100',
162+
},
163+
},
164+
};
165+
const preparedDataWarning = preparePDiskDataResponse([dataWarning, {}]);
166+
167+
expect(
168+
preparedDataWarning.SlotItems?.find((slot) => slot.SlotType === 'log')?.Severity,
169+
).toEqual(3);
170+
171+
const dataDanger: TPDiskInfoResponse = {
172+
...rawData,
173+
Whiteboard: {
174+
...rawData.Whiteboard,
175+
PDisk: {
176+
...rawData.Whiteboard?.PDisk,
177+
LogUsedSize: '99',
178+
LogTotalSize: '100',
179+
},
180+
},
181+
};
182+
const preparedDataDanger = preparePDiskDataResponse([dataDanger, {}]);
183+
184+
expect(
185+
preparedDataDanger.SlotItems?.find((slot) => slot.SlotType === 'log')?.Severity,
186+
).toEqual(5);
187+
});
188+
it('Should return yellow or red severity for vdisk if its size exceeds thresholds', () => {
189+
const dataWarning: TPDiskInfoResponse = {
190+
...rawData,
191+
Whiteboard: {
192+
...rawData.Whiteboard,
193+
VDisks: [
194+
{
195+
...rawData.Whiteboard?.VDisks?.[0],
196+
AllocatedSize: '90',
197+
AvailableSize: '10',
198+
},
199+
],
200+
},
201+
};
202+
const preparedDataWarning = preparePDiskDataResponse([dataWarning, {}]);
203+
204+
expect(
205+
preparedDataWarning.SlotItems?.find((slot) => slot.SlotType === 'vDisk')?.Severity,
206+
).toEqual(3);
207+
208+
const dataDanger: TPDiskInfoResponse = {
209+
...rawData,
210+
Whiteboard: {
211+
...rawData.Whiteboard,
212+
VDisks: [
213+
{
214+
...rawData.Whiteboard?.VDisks?.[0],
215+
AllocatedSize: '99',
216+
AvailableSize: '1',
217+
},
218+
],
219+
},
220+
};
221+
const preparedDataDanger = preparePDiskDataResponse([dataDanger, {}]);
222+
223+
expect(
224+
preparedDataDanger.SlotItems?.find((slot) => slot.SlotType === 'vDisk')?.Severity,
225+
).toEqual(5);
226+
});
227+
});

src/store/reducers/pdisk/utils.ts

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {TPDiskInfoResponse} from '../../../types/api/pdisk';
22
import type {TEvSystemStateResponse} from '../../../types/api/systemState';
33
import {getArray, valueIsDefined} from '../../../utils';
4+
import {getSpaceSeverity} from '../../../utils/disks/helpers';
45
import {
56
prepareWhiteboardPDiskData,
67
prepareWhiteboardVDiskData,
@@ -34,18 +35,20 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
3435
TotalSize: PDiskTotalSize,
3536
SystemSize,
3637
ExpectedSlotCount,
37-
EnforcedDynamicSlotSize,
38+
SlotSize,
3839
} = preparedPDisk;
3940

4041
let logSlot: SlotItem<'log'> | undefined;
4142

4243
if (valueIsDefined(LogTotalSize)) {
44+
const usagePercent = (Number(LogUsedSize) * 100) / Number(LogTotalSize);
45+
4346
logSlot = {
4447
SlotType: 'log',
4548
Used: Number(LogUsedSize),
4649
Total: Number(LogTotalSize),
47-
UsagePercent: (Number(LogUsedSize) * 100) / Number(LogTotalSize),
48-
Severity: 1,
50+
UsagePercent: usagePercent,
51+
Severity: getSpaceSeverity(usagePercent),
4952
SlotData: {
5053
LogUsedSize,
5154
LogTotalSize,
@@ -60,11 +63,19 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
6063
preparedVDisks.sort((disk1, disk2) => Number(disk2.VDiskSlotId) - Number(disk1.VDiskSlotId));
6164

6265
const vdisksSlots: SlotItem<'vDisk'>[] = preparedVDisks.map((preparedVDisk) => {
66+
// VDisks do not have strict limits and can be bigger than they should
67+
// In most storage views we don't colorize them depending on space usage
68+
// Colorize them inside PDiskSpaceDistribution so overused slots will be visible
69+
const slotSeverity = Math.max(
70+
getSpaceSeverity(preparedVDisk.AllocatedPercent),
71+
preparedVDisk.Severity || 0,
72+
);
73+
6374
return {
6475
SlotType: 'vDisk',
6576
Id: preparedVDisk.VDiskId?.GroupID,
6677
Title: preparedVDisk.StoragePoolName,
67-
Severity: preparedVDisk.Severity,
78+
Severity: slotSeverity,
6879
Used: Number(preparedVDisk.AllocatedSize),
6980
Total: Number(preparedVDisk.TotalSize),
7081
UsagePercent: preparedVDisk.AllocatedPercent,
@@ -78,7 +89,7 @@ export function preparePDiskDataResponse([pdiskResponse = {}, nodeResponse]: [
7889
if (ExpectedSlotCount && ExpectedSlotCount > vdisksSlots.length) {
7990
const emptySlotsCount = ExpectedSlotCount - vdisksSlots.length;
8091

81-
let emptySlotSize = Number(EnforcedDynamicSlotSize);
92+
let emptySlotSize = Number(SlotSize);
8293

8394
if (isNaN(emptySlotSize)) {
8495
const vDisksTotalSize = vdisksSlots.reduce((sum, item) => {

0 commit comments

Comments
 (0)