Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: get info about topic children from overview #1489

Merged
merged 1 commit into from
Oct 17, 2024
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
45 changes: 13 additions & 32 deletions src/containers/Tenant/Diagnostics/Describe/Describe.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {ClipboardButton} from '@gravity-ui/uikit';
import {skipToken} from '@reduxjs/toolkit/query';
import JSONTree from 'react-json-inspector';
import {shallowEqual} from 'react-redux';

import {ResponseError} from '../../../../components/Errors/ResponseError';
import {Loader} from '../../../../components/Loader';
import {overviewApi} from '../../../../store/reducers/overview/overview';
import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema/schema';
import {
selectSchemaMergedChildrenPaths,
useGetMultiOverviewQuery,
} from '../../../../store/reducers/overview/overview';
import type {EPathType} from '../../../../types/api/schema';
import type {IDescribeData} from '../../../../types/store/describe';
import {cn} from '../../../../utils/cn';
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
import {isEntityWithMergedImplementation} from '../../utils/schema';
Expand All @@ -26,8 +26,6 @@ interface IDescribeProps {
type?: EPathType;
}

const emptyObject: IDescribeData = {};

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

Expand All @@ -44,37 +42,20 @@ const Describe = ({path, database, type}: IDescribeProps) => {
} else if (mergedChildrenPaths) {
paths = [path, ...mergedChildrenPaths];
}
const {currentDescribe, currentData, isFetching, error} = overviewApi.useGetOverviewQuery(
paths.length ? {paths, database} : skipToken,
{
pollingInterval: autoRefreshInterval,
selectFromResult: (props) => {
const {currentData} = props;
if (!currentData) {
return {currentDescribe: emptyObject, ...props};
}

const mergedData = [currentData.data, ...currentData.additionalData];

const data = mergedData.reduce<IDescribeData>((acc, item) => {
if (item?.Path) {
acc[item.Path] = item;
}
return acc;
}, {});
return {currentDescribe: data, ...props};
},
},
);
const loading = isFetching && currentData === undefined;
const {mergedDescribe, loading, error} = useGetMultiOverviewQuery({
paths,
autoRefreshInterval,
database,
});

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

Expand Down
5 changes: 2 additions & 3 deletions src/containers/Tenant/Diagnostics/HotKeys/HotKeys.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,15 @@ export function HotKeys({path, database}: HotKeysProps) {
const {currentData: data, isFetching, error} = hotKeysApi.useGetHotKeysQuery({path, database});
const loading = isFetching && data === undefined;
const [autoRefreshInterval] = useAutoRefreshInterval();
const {currentData, isLoading: schemaLoading} = overviewApi.useGetOverviewQuery(
const {currentData: schemaData, isLoading: schemaLoading} = overviewApi.useGetOverviewQuery(
{
paths: [path],
path,
database,
},
{
pollingInterval: autoRefreshInterval,
},
);
const {data: schemaData} = currentData ?? {};
const keyColumnsIds = schemaData?.PathDescription?.Table?.KeyColumnNames;

const tableColumns = React.useMemo(() => {
Expand Down
50 changes: 29 additions & 21 deletions src/containers/Tenant/Diagnostics/Overview/Overview.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';

import {skipToken} from '@reduxjs/toolkit/query';
import {shallowEqual} from 'react-redux';

import {ResponseError} from '../../../../components/Errors/ResponseError';
import {TableIndexInfo} from '../../../../components/InfoViewer/schemaInfo';
import {Loader} from '../../../../components/Loader';
import {overviewApi} from '../../../../store/reducers/overview/overview';
import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema/schema';
import {
selectSchemaMergedChildrenPaths,
useGetMultiOverviewQuery,
} from '../../../../store/reducers/overview/overview';
import {EPathType} from '../../../../types/api/schema';
import {useAutoRefreshInterval, useTypedSelector} from '../../../../utils/hooks';
import {ExternalDataSourceInfo} from '../../Info/ExternalDataSource/ExternalDataSource';
Expand Down Expand Up @@ -45,16 +46,17 @@ function Overview({type, path, database}: OverviewProps) {
}

const {
currentData,
isFetching,
error: overviewError,
} = overviewApi.useGetOverviewQuery(paths.length ? {paths, database} : skipToken, {
pollingInterval: autoRefreshInterval,
mergedDescribe,
loading: entityLoading,
error,
} = useGetMultiOverviewQuery({
paths,
database,
autoRefreshInterval,
});
const overviewLoading = isFetching && currentData === undefined;
const {data: rawData, additionalData} = currentData || {};

const entityLoading = overviewLoading;
const rawData = mergedDescribe[path];

const entityNotReady = isEntityWithMergedImpl && !mergedChildrenPaths;

const renderContent = () => {
Expand All @@ -70,14 +72,20 @@ function Overview({type, path, database}: OverviewProps) {
[EPathType.EPathTypeExtSubDomain]: undefined,
[EPathType.EPathTypeColumnStore]: undefined,
[EPathType.EPathTypeColumnTable]: undefined,
[EPathType.EPathTypeCdcStream]: () => (
<ChangefeedInfo
path={path}
database={database}
data={data}
topic={additionalData?.[0] ?? undefined}
/>
),
[EPathType.EPathTypeCdcStream]: () => {
const topicPath = mergedChildrenPaths?.[0];
if (topicPath) {
return (
<ChangefeedInfo
path={path}
database={database}
data={data}
topic={mergedDescribe?.[topicPath] ?? undefined}
/>
);
}
return undefined;
},
[EPathType.EPathTypePersQueueGroup]: () => (
<TopicInfo data={data} path={path} database={database} />
),
Expand All @@ -96,8 +104,8 @@ function Overview({type, path, database}: OverviewProps) {

return (
<React.Fragment>
{overviewError ? <ResponseError error={overviewError} /> : null}
{overviewError && !rawData ? null : renderContent()}
{error ? <ResponseError error={error} /> : null}
{error && !rawData ? null : renderContent()}
</React.Fragment>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,15 @@ export function TenantOverview({

const tenantType = mapDatabaseTypeToDBName(Type);
// FIXME: remove after correct data is added to tenantInfo
const {currentData} = overviewApi.useGetOverviewQuery(
const {currentData: tenantSchemaData} = overviewApi.useGetOverviewQuery(
{
paths: [tenantName],
path: tenantName,
database: tenantName,
},
{
pollingInterval: autoRefreshInterval,
},
);
const {data: tenantSchemaData} = currentData ?? {};
const {Tables, Topics} =
tenantSchemaData?.PathDescription?.DomainDescription?.DiskSpaceUsage || {};

Expand Down
5 changes: 2 additions & 3 deletions src/containers/Tenant/ObjectSummary/ObjectSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,15 @@ export function ObjectSummary({
ignoreQueryPrefix: true,
});

const {currentData} = overviewApi.useGetOverviewQuery(
const {currentData: currentObjectData} = overviewApi.useGetOverviewQuery(
{
paths: [path],
path,
database: tenantName,
},
{
pollingInterval: autoRefreshInterval,
},
);
const {data: currentObjectData} = currentData ?? {};
const currentSchemaData = currentObjectData?.PathDescription?.Self;

React.useEffect(() => {
Expand Down
6 changes: 2 additions & 4 deletions src/containers/Tenant/Schema/SchemaViewer/SchemaViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,16 @@ interface SchemaViewerProps {

export const SchemaViewer = ({type, path, tenantName, extended = false}: SchemaViewerProps) => {
const [autoRefreshInterval] = useAutoRefreshInterval();
const {currentData, isLoading: loading} = overviewApi.useGetOverviewQuery(
const {currentData: schemaData, isLoading: loading} = overviewApi.useGetOverviewQuery(
{
paths: [path],
path,
database: tenantName,
},
{
pollingInterval: autoRefreshInterval,
},
);

const {data: schemaData} = currentData ?? {};

const viewSchemaRequestParams = isViewType(type) ? {path, database: tenantName} : skipToken;

const {data: viewColumnsData, isLoading: isViewSchemaLoading} =
Expand Down
9 changes: 6 additions & 3 deletions src/containers/Tenant/Tenant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,16 @@ export function Tenant(props: TenantProps) {

const path = schema ?? tenantName;

const {currentData, error, isLoading} = overviewApi.useGetOverviewQuery(
{paths: [path], database: tenantName},
const {
currentData: currentItem,
error,
isLoading,
} = overviewApi.useGetOverviewQuery(
{path, database: tenantName},
{
pollingInterval: autoRefreshInterval,
},
);
const {data: currentItem} = currentData ?? {};
const {PathType: currentPathType, PathSubType: currentPathSubType} =
currentItem?.PathDescription?.Self || {};

Expand Down
114 changes: 111 additions & 3 deletions src/store/reducers/overview/overview.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import {createSelector} from '@reduxjs/toolkit';
import {skipToken} from '@reduxjs/toolkit/query';

import {isEntityWithMergedImplementation} from '../../../containers/Tenant/utils/schema';
import type {EPathType} from '../../../types/api/schema';
import type {IDescribeData} from '../../../types/store/describe';
import type {RootState} from '../../defaultStore';
import {api} from '../api';

export const overviewApi = api.injectEndpoints({
endpoints: (build) => ({
getOverview: build.query({
getMultiOverview: build.query({
queryFn: async ({paths, database}: {paths: string[]; database: string}, {signal}) => {
try {
const [data, ...additionalData] = await Promise.all(
const data = await Promise.all(
paths.map((p) =>
window.api.getDescribe(
{
Expand All @@ -16,7 +23,25 @@ export const overviewApi = api.injectEndpoints({
),
),
);
return {data: {data, additionalData}};
return {data};
} catch (error) {
return {error};
}
},
keepUnusedDataFor: 0,
providesTags: ['All'],
}),
getOverview: build.query({
queryFn: async ({path, database}: {path: string; database: string}, {signal}) => {
try {
const data = await window.api.getDescribe(
{
path,
database,
},
{signal},
);
return {data};
} catch (error) {
return {error};
}
Expand All @@ -26,3 +51,86 @@ export const overviewApi = api.injectEndpoints({
}),
}),
});

const getOverviewSelector = createSelector(
(path: string) => path,
(_path: string, database: string) => database,
(path, database) => overviewApi.endpoints.getOverview.select({path, database}),
);

const selectGetOverview = createSelector(
(state: RootState) => state,
(_state: RootState, path: string, database: string) => getOverviewSelector(path, database),
(state, selectOverview) => selectOverview(state).data,
);

const selectOverviewChildren = (state: RootState, path: string, database: string) =>
selectGetOverview(state, path, database)?.PathDescription?.Children;

export const selectSchemaMergedChildrenPaths = createSelector(
[
(_, path: string) => path,
(_, _path, type: EPathType | undefined) => type,
(state, path, _type, database: string) => selectOverviewChildren(state, path, database),
],
(path, type, children) => {
return isEntityWithMergedImplementation(type)
? children?.map(({Name}) => path + '/' + Name)
: undefined;
},
);

//this hook is done not to refetch mainPath describe for entities with merged implementation
export function useGetMultiOverviewQuery({
paths,
database,
autoRefreshInterval,
}: {
paths: string[];
database: string;
autoRefreshInterval?: number;
}) {
const [mainPath, ...additionalPaths] = paths;

const {
currentData: mainDescribe,
isFetching: mainDescribeIsFetching,
error: mainDescribeError,
} = overviewApi.useGetOverviewQuery(
{
path: mainPath,
database,
},
{
pollingInterval: autoRefreshInterval,
},
);

const {
currentData: currentChindrenDescribe = [],
isFetching: childrenDescribeIsFetching,
error: childrenDescribeError,
} = overviewApi.useGetMultiOverviewQuery(
additionalPaths.length ? {paths: additionalPaths, database} : skipToken,
{
pollingInterval: autoRefreshInterval,
},
);

const childrenDescribeLoading =
childrenDescribeIsFetching && currentChindrenDescribe === undefined;
const mainDescribeLoading = mainDescribeIsFetching && mainDescribe === undefined;

const loading = mainDescribeLoading || childrenDescribeLoading;

const describe = [mainDescribe, ...currentChindrenDescribe];

const mergedDescribe = describe.reduce<IDescribeData>((acc, item) => {
if (item?.Path) {
acc[item.Path] = item;
}
return acc;
}, {});

return {loading, error: mainDescribeError || childrenDescribeError, mergedDescribe};
}
Loading
Loading