Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 12 additions & 42 deletions src/containers/Tenant/Diagnostics/Describe/Describe.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import {ClipboardButton} from '@gravity-ui/uikit';
import {shallowEqual} from 'react-redux';

import {ResponseError} from '../../../../components/Errors/ResponseError';
import {JsonViewer} from '../../../../components/JsonViewer/JsonViewer';
import {useUnipikaConvert} from '../../../../components/JsonViewer/unipika/unipika';
import {Loader} from '../../../../components/Loader';
import {
selectSchemaMergedChildrenPaths,
useGetMultiOverviewQuery,
} from '../../../../store/reducers/overview/overview';
import type {EPathType} from '../../../../types/api/schema';
import {overviewApi} from '../../../../store/reducers/overview/overview';
import {cn} from '../../../../utils/cn';
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
import {isEntityWithMergedImplementation} from '../../utils/schema';
import {useAutoRefreshInterval} from '../../../../utils/hooks';

import './Describe.scss';

Expand All @@ -21,63 +15,39 @@ const b = cn('ydb-describe');
interface IDescribeProps {
path: string;
database: string;
type?: EPathType;
}

const Describe = ({path, database, type}: IDescribeProps) => {
const Describe = ({path, database}: IDescribeProps) => {
const [autoRefreshInterval] = useAutoRefreshInterval();

const isEntityWithMergedImpl = isEntityWithMergedImplementation(type);

const mergedChildrenPaths = useTypedSelector(
(state) => selectSchemaMergedChildrenPaths(state, path, type, database),
shallowEqual,
const {currentData, isFetching, error} = overviewApi.useGetOverviewQuery(
{path, database},
{pollingInterval: autoRefreshInterval},
);

let paths: string[] = [];
if (!isEntityWithMergedImpl) {
paths = [path];
} else if (mergedChildrenPaths) {
paths = [path, ...mergedChildrenPaths];
}

const {mergedDescribe, loading, error} = useGetMultiOverviewQuery({
paths,
autoRefreshInterval,
database,
});

let preparedDescribeData: Object | undefined;
if (mergedDescribe) {
const paths = Object.keys(mergedDescribe);
if (paths.length === 1) {
preparedDescribeData = mergedDescribe[paths[0]];
} else {
preparedDescribeData = mergedDescribe;
}
}
const loading = isFetching && currentData === undefined;

const convertedValue = useUnipikaConvert(preparedDescribeData);
const convertedValue = useUnipikaConvert(currentData);

if (loading || (isEntityWithMergedImpl && !mergedChildrenPaths)) {
if (loading) {
return <Loader size="m" />;
}

if (!preparedDescribeData && !error) {
if (!currentData && !error) {
return <div className={b('message-container')}>Empty</div>;
}

return (
<div className={b()}>
{error ? <ResponseError error={error} /> : null}
{preparedDescribeData ? (
{currentData ? (
<div className={b('result')}>
<JsonViewer
value={convertedValue}
extraTools={
<ClipboardButton
view="flat-secondary"
text={JSON.stringify(preparedDescribeData)}
text={JSON.stringify(currentData)}
/>
}
search
Expand Down
7 changes: 4 additions & 3 deletions src/containers/Tenant/Diagnostics/Diagnostics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
import {setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
import type {AdditionalNodesProps, AdditionalTenantsProps} from '../../../types/additionalProps';
import type {EPathType} from '../../../types/api/schema';
import type {EPathSubType, EPathType} from '../../../types/api/schema';
import {cn} from '../../../utils/cn';
import {useTypedDispatch, useTypedSelector} from '../../../utils/hooks';
import {Heatmap} from '../../Heatmap';
Expand All @@ -40,6 +40,7 @@ import './Diagnostics.scss';

interface DiagnosticsProps {
type?: EPathType;
subType?: EPathSubType;
tenantName: string;
path: string;
additionalTenantProps?: AdditionalTenantsProps;
Expand All @@ -62,7 +63,7 @@ function Diagnostics(props: DiagnosticsProps) {

const hasFeatureFlags = useFeatureFlagsAvailable();
const hasTopicData = useTopicDataAvailable();
const pages = getPagesByType(props.type, {
const pages = getPagesByType(props.type, props.subType, {
hasFeatureFlags,
hasTopicData,
isTopLevel: props.path === props.tenantName,
Expand Down Expand Up @@ -129,7 +130,7 @@ function Diagnostics(props: DiagnosticsProps) {
);
}
case TENANT_DIAGNOSTICS_TABS_IDS.describe: {
return <Describe path={path} database={tenantName} type={type} />;
return <Describe path={path} database={tenantName} />;
}
case TENANT_DIAGNOSTICS_TABS_IDS.hotKeys: {
return <HotKeys path={path} database={tenantName} />;
Expand Down
21 changes: 15 additions & 6 deletions src/containers/Tenant/Diagnostics/DiagnosticsPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {StringParam, useQueryParams} from 'use-query-params';

import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
import type {TenantDiagnosticsTab} from '../../../store/reducers/tenant/types';
import {EPathType} from '../../../types/api/schema';
import {EPathSubType, EPathType} from '../../../types/api/schema';
import type {TenantQuery} from '../TenantPages';
import {TenantTabsGroups, getTenantPath} from '../TenantPages';
import {isDatabaseEntityType, isTopicEntityType} from '../utils/schema';
Expand Down Expand Up @@ -113,7 +113,8 @@ const COLUMN_TABLE_PAGES = [overview, schema, topShards, nodes, tablets, describ

const DIR_PAGES = [overview, topShards, nodes, describe];

const CDC_STREAM_PAGES = [overview, consumers, partitions, nodes, tablets, describe];
const CDC_STREAM_PAGES = [overview, consumers, partitions, nodes, describe];
const CDC_STREAM_IMPL_PAGES = [overview, nodes, tablets, describe];
const TOPIC_PAGES = [overview, consumers, partitions, topicData, nodes, tablets, describe];

const EXTERNAL_DATA_SOURCE_PAGES = [overview, describe];
Expand Down Expand Up @@ -149,15 +150,23 @@ const pathTypeToPages: Record<EPathType, Page[] | undefined> = {
[EPathType.EPathTypeTransfer]: TRANSFER_PAGES,
[EPathType.EPathTypeResourcePool]: DIR_PAGES,
};
const pathSubTypeToPages: Record<EPathSubType, Page[] | undefined> = {
[EPathSubType.EPathSubTypeStreamImpl]: CDC_STREAM_IMPL_PAGES,

[EPathSubType.EPathSubTypeSyncIndexImplTable]: undefined,
[EPathSubType.EPathSubTypeAsyncIndexImplTable]: undefined,
[EPathSubType.EPathSubTypeEmpty]: undefined,
};

export const getPagesByType = (
type?: EPathType,
subType?: EPathSubType,
options?: {hasFeatureFlags?: boolean; hasTopicData?: boolean; isTopLevel?: boolean},
) => {
if (!type || !pathTypeToPages[type]) {
return DIR_PAGES;
}
let pages = pathTypeToPages[type];
const subTypePages = subType ? pathSubTypeToPages[subType] : undefined;
const typePages = type ? pathTypeToPages[type] : undefined;
let pages = subTypePages || typePages || DIR_PAGES;

if (isTopicEntityType(type) && !options?.hasTopicData) {
return pages?.filter((item) => item.id !== TENANT_DIAGNOSTICS_TABS_IDS.topicData);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@ import {
import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
import {getEntityName} from '../../../utils';
import {TopicStats} from '../TopicStats';
import {prepareTopicSchemaInfo} from '../utils';

const prepareChangefeedInfo = (
changefeedData?: TEvDescribeSchemeResult,
topicData?: TEvDescribeSchemeResult,
): Array<InfoViewerItem> => {
if (!changefeedData && !topicData) {
const prepareChangefeedInfo = (changefeedData?: TEvDescribeSchemeResult): Array<InfoViewerItem> => {
if (!changefeedData) {
return [];
}

Expand All @@ -25,17 +21,14 @@ const prepareChangefeedInfo = (
Mode,
Format,
});
const topicInfo = prepareTopicSchemaInfo(topicData);

const info = [...changefeedInfo, ...topicInfo];

const createStep = changefeedData?.PathDescription?.Self?.CreateStep;

if (Number(createStep)) {
info.unshift(formatCommonItem('CreateStep', createStep));
changefeedInfo.unshift(formatCommonItem('CreateStep', createStep));
}

return info;
return changefeedInfo;
};

interface ChangefeedProps {
Expand All @@ -46,16 +39,16 @@ interface ChangefeedProps {
}

/** Displays overview for CDCStream EPathType */
export const ChangefeedInfo = ({path, database, data, topic}: ChangefeedProps) => {
export const ChangefeedInfo = ({path, database, data}: ChangefeedProps) => {
const entityName = getEntityName(data?.PathDescription);

if (!data || !topic) {
if (!data) {
return <div className="error">No {entityName} data</div>;
}

return (
<div>
<InfoViewer title={entityName} info={prepareChangefeedInfo(data, topic)} />
<InfoViewer title={entityName} info={prepareChangefeedInfo(data)} />
<TopicStats path={path} database={database} />
</div>
);
Expand Down
63 changes: 12 additions & 51 deletions src/containers/Tenant/Diagnostics/Overview/Overview.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import React from 'react';

import {shallowEqual} from 'react-redux';

import {ResponseError} from '../../../../components/Errors/ResponseError';
import {TableIndexInfo} from '../../../../components/InfoViewer/schemaInfo';
import {Loader} from '../../../../components/Loader';
import {
selectSchemaMergedChildrenPaths,
useGetMultiOverviewQuery,
} from '../../../../store/reducers/overview/overview';
import {overviewApi} from '../../../../store/reducers/overview/overview';
import {EPathType} from '../../../../types/api/schema';
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
import {useAutoRefreshInterval} from '../../../../utils/hooks';
import {ExternalDataSourceInfo} from '../../Info/ExternalDataSource/ExternalDataSource';
import {ExternalTableInfo} from '../../Info/ExternalTable/ExternalTable';
import {ViewInfo} from '../../Info/View/View';
import {isEntityWithMergedImplementation} from '../../utils/schema';

import {AsyncReplicationInfo} from './AsyncReplicationInfo';
import {ChangefeedInfo} from './ChangefeedInfo';
Expand All @@ -31,37 +25,15 @@ interface OverviewProps {
function Overview({type, path, database}: OverviewProps) {
const [autoRefreshInterval] = useAutoRefreshInterval();

const isEntityWithMergedImpl = isEntityWithMergedImplementation(type);

// shallowEqual prevents rerenders when new schema data is loaded
const mergedChildrenPaths = useTypedSelector(
(state) => selectSchemaMergedChildrenPaths(state, path, type, database),
shallowEqual,
const {currentData, isFetching, error} = overviewApi.useGetOverviewQuery(
{path, database},
{pollingInterval: autoRefreshInterval},
);

let paths: string[] = [];
if (!isEntityWithMergedImpl) {
paths = [path];
} else if (mergedChildrenPaths) {
paths = [path, ...mergedChildrenPaths];
}

const {
mergedDescribe,
loading: entityLoading,
error,
} = useGetMultiOverviewQuery({
paths,
database,
autoRefreshInterval,
});

const rawData = mergedDescribe[path];

const entityNotReady = isEntityWithMergedImpl && !mergedChildrenPaths;
const loading = isFetching && currentData === undefined;

const renderContent = () => {
const data = rawData ?? undefined;
const data = currentData ?? undefined;
// verbose mapping to guarantee a correct render for new path types
// TS will error when a new type is added but not mapped here
const pathTypeToComponent: Record<EPathType, (() => React.ReactNode) | undefined> = {
Expand All @@ -74,20 +46,9 @@ function Overview({type, path, database}: OverviewProps) {
[EPathType.EPathTypeExtSubDomain]: undefined,
[EPathType.EPathTypeColumnStore]: undefined,
[EPathType.EPathTypeColumnTable]: undefined,
[EPathType.EPathTypeCdcStream]: () => {
const topicPath = mergedChildrenPaths?.[0];
if (topicPath) {
return (
<ChangefeedInfo
path={path}
database={database}
data={data}
topic={mergedDescribe?.[topicPath] ?? undefined}
/>
);
}
return undefined;
},
[EPathType.EPathTypeCdcStream]: () => (
<ChangefeedInfo path={path} database={database} data={data} />
),
[EPathType.EPathTypePersQueueGroup]: () => (
<TopicInfo data={data} path={path} database={database} />
),
Expand All @@ -103,14 +64,14 @@ function Overview({type, path, database}: OverviewProps) {
return (type && pathTypeToComponent[type]?.()) || <TableInfo data={data} type={type} />;
};

if (entityLoading || entityNotReady) {
if (loading) {
return <Loader size="m" />;
}

return (
<React.Fragment>
{error ? <ResponseError error={error} /> : null}
{error && !rawData ? null : renderContent()}
{error && !currentData ? null : renderContent()}
</React.Fragment>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {InfoViewer} from '../../../../../components/InfoViewer';
import {EPathSubType} from '../../../../../types/api/schema';
import type {TEvDescribeSchemeResult} from '../../../../../types/api/schema';
import {getEntityName} from '../../../utils';
import {TopicStats} from '../TopicStats';
Expand All @@ -18,10 +19,19 @@ export const TopicInfo = ({data, path, database}: TopicInfoProps) => {
return <div className="error">No {entityName} data</div>;
}

const renderStats = () => {
// In case of stream impl we display stats in CDC info tab instead
if (data.PathDescription?.Self?.PathSubType === EPathSubType.EPathSubTypeStreamImpl) {
return null;
}

return <TopicStats path={path} database={database} />;
};

return (
<div>
<InfoViewer title={entityName} info={prepareTopicSchemaInfo(data)} />
<TopicStats path={path} database={database} />
{renderStats()}
</div>
);
};
Loading
Loading