Skip to content

Commit e1878a6

Browse files
committed
feat(Tenant): pq groups info & overview
1 parent 068b40a commit e1878a6

File tree

11 files changed

+295
-3
lines changed

11 files changed

+295
-3
lines changed

src/components/InfoViewer/formatters/schema.ts

+17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import type {
22
TCdcStreamDescription,
33
TIndexDescription,
4+
TPersQueueGroupDescription,
45
} from '../../../types/api/schema';
6+
import {formatNumber} from '../../../utils';
7+
import {HOUR_IN_SECONDS} from '../../../utils/constants';
58

69
import {createInfoFormatter} from '../utils';
710

@@ -24,3 +27,17 @@ export const formatCdcStreamItem = createInfoFormatter<TCdcStreamDescription>({
2427
Format: (value) => value?.substring('ECdcStreamFormat'.length),
2528
},
2629
});
30+
31+
export const formatPQGroupItem = createInfoFormatter<TPersQueueGroupDescription>({
32+
values: {
33+
Partitions: (value) => formatNumber(value?.length || 0),
34+
PQTabletConfig: (value) => {
35+
const hours = Math.round(value.PartitionConfig.LifetimeSeconds / HOUR_IN_SECONDS * 100) / 100;
36+
return `${formatNumber(hours)} hours`;
37+
},
38+
},
39+
labels: {
40+
Partitions: 'Partitions count',
41+
PQTabletConfig: 'Retention',
42+
},
43+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type {TEvDescribeSchemeResult} from '../../../types/api/schema';
2+
3+
import {formatCommonItem, formatPQGroupItem} from '../formatters';
4+
import {InfoViewer, InfoViewerItem} from '..';
5+
6+
interface PersQueueGrouopInfoProps {
7+
data?: TEvDescribeSchemeResult;
8+
}
9+
10+
export const PersQueueGroupInfo = ({data}: PersQueueGrouopInfoProps) => {
11+
if (!data) {
12+
return (
13+
<div className="error">No PersQueueGroup data</div>
14+
);
15+
}
16+
17+
const pqGroup = data.PathDescription?.PersQueueGroup;
18+
const info: Array<InfoViewerItem> = [];
19+
20+
info.push(formatCommonItem('PathType', data.PathDescription?.Self?.PathType));
21+
22+
info.push(formatPQGroupItem('Partitions', pqGroup?.Partitions || []));
23+
info.push(formatPQGroupItem('PQTabletConfig', pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}}));
24+
25+
return (
26+
<>
27+
{info.length ? (
28+
<InfoViewer info={info}></InfoViewer>
29+
) : (
30+
<>Empty</>
31+
)}
32+
</>
33+
);
34+
};
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './CDCStreamInfo';
22
export * from './TableIndexInfo';
3+
export * from './PersQueueGroupInfo';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type {TEvDescribeSchemeResult} from '../../../types/api/schema';
2+
3+
import {formatCommonItem, formatPQGroupItem} from '../formatters';
4+
import {InfoViewer, InfoViewerItem} from '..';
5+
6+
interface PersQueueGroupOverviewProps {
7+
data?: TEvDescribeSchemeResult;
8+
}
9+
10+
export const PersQueueGroupOverview = ({data}: PersQueueGroupOverviewProps) => {
11+
if (!data) {
12+
return (
13+
<div className="error">No PersQueueGroup data</div>
14+
);
15+
}
16+
17+
const pqGroup = data.PathDescription?.PersQueueGroup;
18+
const info: Array<InfoViewerItem> = [];
19+
20+
info.push(formatCommonItem('PathType', data.PathDescription?.Self?.PathType));
21+
info.push(formatCommonItem('CreateStep', data.PathDescription?.Self?.CreateStep));
22+
23+
info.push(formatPQGroupItem('Partitions', pqGroup?.Partitions || []));
24+
info.push(formatPQGroupItem('PQTabletConfig', pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}}));
25+
26+
return (
27+
<>
28+
{info.length ? (
29+
<InfoViewer info={info}></InfoViewer>
30+
) : (
31+
<>Empty</>
32+
)}
33+
</>
34+
);
35+
};
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './CDCStreamOverview';
2+
export * from './PersQueueGroupOverview';

src/containers/Tenant/Diagnostics/DiagnosticsPages.ts

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ const pathTypeToPages: Record<EPathType, Page[] | undefined> = {
9999
[EPathType.EPathTypeTableIndex]: DIR_PAGES,
100100

101101
[EPathType.EPathTypeCdcStream]: TOPIC_PAGES,
102+
[EPathType.EPathTypePersQueueGroup]: TOPIC_PAGES,
102103
};
103104

104105
export const getPagesByType = (type?: EPathType) =>

src/containers/Tenant/Diagnostics/Overview/Overview.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import SchemaInfoViewer from '../../Schema/SchemaInfoViewer/SchemaInfoViewer';
99
import {
1010
CDCStreamInfo,
1111
TableIndexInfo,
12+
PersQueueGroupInfo,
1213
} from '../../../../components/InfoViewer/schemaInfo';
1314

1415
import {EPathType} from '../../../../types/api/schema';
@@ -129,6 +130,7 @@ function Overview(props: OverviewProps) {
129130
[EPathType.EPathTypeColumnStore]: undefined,
130131
[EPathType.EPathTypeColumnTable]: undefined,
131132
[EPathType.EPathTypeCdcStream]: () => <CDCStreamInfo data={schemaData} />,
133+
[EPathType.EPathTypePersQueueGroup]: () => <PersQueueGroupInfo data={schemaData} />,
132134
};
133135

134136
return (props.type && pathTypeToComponent[props.type]?.()) || (

src/containers/Tenant/ObjectSummary/ObjectSummary.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import Acl from '../Acl/Acl';
1414
import SchemaViewer from '../Schema/SchemaViewer/SchemaViewer';
1515
import CopyToClipboard from '../../../components/CopyToClipboard/CopyToClipboard';
1616
import InfoViewer from '../../../components/InfoViewer/InfoViewer';
17-
import {CDCStreamOverview} from '../../../components/InfoViewer/schemaOverview';
17+
import {
18+
CDCStreamOverview,
19+
PersQueueGroupOverview,
20+
} from '../../../components/InfoViewer/schemaOverview';
1821
import Icon from '../../../components/Icon/Icon';
1922

2023
import {EPathSubType, EPathType, TDirEntry} from '../../../types/api/schema';
@@ -164,6 +167,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
164167
[EPathType.EPathTypeColumnStore]: undefined,
165168
[EPathType.EPathTypeColumnTable]: undefined,
166169
[EPathType.EPathTypeCdcStream]: () => <CDCStreamOverview data={data[currentSchemaPath]} />,
170+
[EPathType.EPathTypePersQueueGroup]: () => <PersQueueGroupOverview data={data[currentSchemaPath]} />,
167171
};
168172

169173
let component = currentSchemaData?.PathType && pathTypeToComponent[currentSchemaData.PathType]?.();

src/containers/Tenant/utils/schema.ts

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const pathTypeToNodeType: Record<EPathType, NavigationTreeNodeType | undefined>
2929
[EPathType.EPathTypeColumnTable]: 'column_table',
3030

3131
[EPathType.EPathTypeCdcStream]: 'topic',
32+
[EPathType.EPathTypePersQueueGroup]: 'topic',
3233
};
3334

3435
export const mapPathTypeToNavigationTreeType = (
@@ -51,6 +52,7 @@ const pathTypeToIsTable: Record<EPathType, boolean> = {
5152
[EPathType.EPathTypeExtSubDomain]: false,
5253
[EPathType.EPathTypeColumnStore]: false,
5354
[EPathType.EPathTypeCdcStream]: false,
55+
[EPathType.EPathTypePersQueueGroup]: false,
5456
};
5557

5658
export const isTableType = (pathType?: EPathType) =>
@@ -82,6 +84,7 @@ const pathTypeToIsColumn: Record<EPathType, boolean> = {
8284
[EPathType.EPathTypeTableIndex]: false,
8385
[EPathType.EPathTypeExtSubDomain]: false,
8486
[EPathType.EPathTypeCdcStream]: false,
87+
[EPathType.EPathTypePersQueueGroup]: false,
8588
};
8689

8790
export const isColumnEntityType = (type?: EPathType) =>

src/types/api/schema.ts

+194-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ interface TPathDescription {
5858
TableIndex?: TIndexDescription;
5959

6060
CdcStreamDescription?: TCdcStreamDescription;
61+
PersQueueGroup?: TPersQueueGroupDescription;
6162
}
6263

6364
export interface TDirEntry {
@@ -253,7 +254,7 @@ export enum EPathType {
253254
EPathTypeInvalid = 'EPathTypeInvalid',
254255
EPathTypeDir = 'EPathTypeDir',
255256
EPathTypeTable = 'EPathTypeTable',
256-
257+
EPathTypePersQueueGroup = 'EPathTypePersQueueGroup',
257258
EPathTypeSubDomain = 'EPathTypeSubDomain',
258259

259260
EPathTypeTableIndex = 'EPathTypeTableIndex',
@@ -304,3 +305,195 @@ interface TPathVersion {
304305
/** uint64 */
305306
GeneralVersion?: string;
306307
}
308+
309+
interface TPartitionKeyRange {
310+
// Inclusive left border. Emptiness means -inf.
311+
FromBound?: string;
312+
// Exclusive right border. Emptiness means +inf.
313+
ToBound?: string;
314+
}
315+
316+
interface TPartition {
317+
PartitionId?: number;
318+
/** uint64 */
319+
TabletId?: string;
320+
KeyRange?: TPartitionKeyRange;
321+
}
322+
323+
interface TPartitionToAdd {
324+
PartitionId?: number;
325+
GroupId?: number;
326+
}
327+
328+
interface TCodecs {
329+
/** int64 */
330+
Ids?: string[];
331+
Codecs?: string[];
332+
}
333+
334+
interface TKeyComponentSchema {
335+
Name?: string;
336+
TypeId?: number;
337+
}
338+
339+
enum EMeteringMode {
340+
METERING_MODE_RESERVED_CAPACITY = 'METERING_MODE_RESERVED_CAPACITY',
341+
METERING_MODE_REQUEST_UNITS = 'METERING_MODE_REQUEST_UNITS',
342+
}
343+
344+
interface TReadQuota {
345+
ClientId?: string;
346+
/** uint64 */
347+
SpeedInBytesPerSecond?: string;
348+
/** uint64 */
349+
BurstSize?: string;
350+
}
351+
352+
interface TChannelProfile {
353+
PoolKind?: string;
354+
/** uint64 */
355+
Size?: string;
356+
ReadIops?: number;
357+
ReadBandwidth?: number;
358+
WriteIops?: number;
359+
WriteBandwidth?: number;
360+
}
361+
362+
interface IamCredentials {
363+
Endpoint?: string;
364+
ServiceAccountKey?: string;
365+
}
366+
367+
interface TCredentials {
368+
OauthToken?: string;
369+
JwtParams?: string;
370+
Iam?: IamCredentials;
371+
}
372+
373+
interface TMirrorPartitionConfig {
374+
Endpoint?: string;
375+
EndpointPort?: number;
376+
Topic?: string;
377+
Consumer?: string;
378+
/** uint64 */
379+
ReadFromTimestampsMs?: string;
380+
Credentials?: TCredentials;
381+
Database?: string;
382+
UseSecureConnection?: boolean;
383+
SyncWriteTime?: boolean;
384+
}
385+
386+
interface TPQPartitionConfig {
387+
MaxCountInPartition?: number;
388+
/** int64 */
389+
MaxSizeInPartition?: string;
390+
LifetimeSeconds: number;
391+
/** uint64 */
392+
StorageLimitBytes?: string;
393+
394+
ImportantClientId?: string[];
395+
LowWatermark?: number;
396+
SourceIdLifetimeSeconds?: number;
397+
SourceIdMaxCounts?: number;
398+
399+
/** uint64 */
400+
WriteSpeedInBytesPerSecond?: string;
401+
/** uint64 */
402+
BurstSize?: string;
403+
404+
ReadQuota?: TReadQuota[];
405+
/** uint64 */
406+
MaxWriteInflightSize?: string;
407+
/** uint64 */
408+
BorderWriteInflightSize?: string;
409+
410+
NumChannels?: number;
411+
412+
TotalPartitions?: number;
413+
414+
ExplicitChannelProfiles?: TChannelProfile[];
415+
416+
MirrorFrom?: TMirrorPartitionConfig;
417+
};
418+
419+
interface TPQTabletConfig {
420+
/** uint64 */
421+
CacheSize?: string;
422+
PartitionConfig: TPQPartitionConfig;
423+
/** @deprecated use Partitions */
424+
PartitionIds?: number[];
425+
TopicName?: string;
426+
Version?: number;
427+
LocalDC?: boolean;
428+
RequireAuthWrite?: boolean;
429+
RequireAuthRead?: boolean;
430+
Producer?: string;
431+
Ident?: string;
432+
Topic?: string;
433+
DC?: string;
434+
435+
ReadRules?: string[];
436+
/** uint64[] */
437+
ReadFromTimestampsMs?: number[];
438+
/** uint64[] */
439+
ConsumerFormatVersions?: number[];
440+
441+
ConsumerCodecs?: TCodecs[];
442+
ReadRuleServiceTypes?: string;
443+
444+
/** uint64 */
445+
FormatVersion?: string;
446+
Codecs?: TCodecs;
447+
448+
/** uint64[] */
449+
ReadRuleVersions?: string[];
450+
/** uint64[] */
451+
ReadRuleGenerations?: string[];
452+
453+
TopicPath?: string;
454+
455+
YcCloudId?: string;
456+
YcFolderId?: string;
457+
YdbDatabaseId?: string;
458+
YdbDatabasePath?: string;
459+
FederationAccount?: string;
460+
461+
PartitionKeySchema?: TKeyComponentSchema[];
462+
463+
Partitions?: TPartition[];
464+
465+
MeteringMode?: EMeteringMode;
466+
}
467+
468+
interface TMessageGroup {
469+
// Id of message group (SourceId)
470+
Id?: string;
471+
// Range of the key to which it is allowed to write.
472+
KeyRange?: TPartitionKeyRange;
473+
}
474+
475+
interface TBootstrapConfig {
476+
ExplicitMessageGroups?: TMessageGroup[];
477+
}
478+
479+
export interface TPersQueueGroupDescription {
480+
Name: string;
481+
/** uint64 */
482+
PathId?: string;
483+
TotalGroupCount: number;
484+
485+
PartitionsToAdd?: TPartitionToAdd[];
486+
PartitionsToDelete?: number[];
487+
NextPartitionId?: number;
488+
PartitionPerTablet?: number;
489+
PQTabletConfig: TPQTabletConfig;
490+
Partitions?: TPartition[];
491+
/** uint64 */
492+
AlterVersion?: string;
493+
/** uint64 */
494+
BalancerTabletID?: string;
495+
496+
PartitionBoundaries?: any;
497+
498+
BootstrapConfig?: TBootstrapConfig;
499+
}

src/utils/constants.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export const GIGABYTE = 1_000_000_000;
1414
export const TERABYTE = 1_000_000_000_000;
1515
export const GROUP = 'group';
1616

17-
export const DAY_IN_SECONDS = 24 * 60 * 60;
17+
export const HOUR_IN_SECONDS = 60 * 60;
18+
export const DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS;
1819

1920
export const TABLET_STATES = {
2021
TABLET_VOLATILE_STATE_UNKNOWN: 'unknown',

0 commit comments

Comments
 (0)