diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx
index 1f117115b..fb14e5bf0 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx
@@ -41,7 +41,16 @@ export function HealthcheckPreview(props: HealthcheckPreviewProps) {
{i18n('title.healthcheck')}
-
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx
index 41a17d9d6..1044edb86 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.tsx
@@ -1,18 +1,8 @@
-import React from 'react';
-
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
-import {
- getTopNodesByCpu,
- selectTopNodesByCpu,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu';
+import {topNodesApi} from '../../../../../store/reducers/tenantOverview/topNodes/topNodes';
import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
-import {
- useAutofetcher,
- useSearchQuery,
- useTypedDispatch,
- useTypedSelector,
-} from '../../../../../utils/hooks';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useSearchQuery, useTypedSelector} from '../../../../../utils/hooks';
import {getTopNodesByCpuColumns} from '../../../../Nodes/getNodesColumns';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
@@ -25,27 +15,18 @@ interface TopNodesByCpuProps {
}
export function TopNodesByCpu({path, additionalNodesProps}: TopNodesByCpuProps) {
- const dispatch = useTypedDispatch();
-
const query = useSearchQuery();
- const {wasLoaded, loading, error} = useTypedSelector((state) => state.topNodesByCpu);
const {autorefresh} = useTypedSelector((state) => state.schema);
- const topNodes = useTypedSelector(selectTopNodesByCpu);
const columns = getTopNodesByCpuColumns(additionalNodesProps?.getNodeRef);
- const fetchNodes = React.useCallback(
- (isBackground: boolean) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
-
- dispatch(getTopNodesByCpu({tenant: path}));
- },
- [dispatch, path],
+ const {currentData, isFetching, error} = topNodesApi.useGetTopNodesQuery(
+ {tenant: path, sortValue: 'CPU'},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
- useAutofetcher(fetchNodes, [fetchNodes], autorefresh);
+ const loading = isFetching && currentData === undefined;
+ const topNodes = currentData;
const title = getSectionTitle({
entity: i18n('nodes'),
@@ -62,7 +43,6 @@ export function TopNodesByCpu({path, additionalNodesProps}: TopNodesByCpuProps)
columns={columns}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
emptyDataMessage={i18n('top-nodes.empty-data')}
/>
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx
index 274e5ee4f..5da25aa5b 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.tsx
@@ -1,18 +1,8 @@
-import React from 'react';
-
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
-import {
- getTopNodesByLoad,
- selectTopNodesByLoad,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad';
+import {topNodesApi} from '../../../../../store/reducers/tenantOverview/topNodes/topNodes';
import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
-import {
- useAutofetcher,
- useSearchQuery,
- useTypedDispatch,
- useTypedSelector,
-} from '../../../../../utils/hooks';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useSearchQuery, useTypedSelector} from '../../../../../utils/hooks';
import {getTopNodesByLoadColumns} from '../../../../Nodes/getNodesColumns';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
@@ -25,27 +15,18 @@ interface TopNodesByLoadProps {
}
export function TopNodesByLoad({path, additionalNodesProps}: TopNodesByLoadProps) {
- const dispatch = useTypedDispatch();
-
const query = useSearchQuery();
- const {wasLoaded, loading, error} = useTypedSelector((state) => state.topNodesByLoad);
const {autorefresh} = useTypedSelector((state) => state.schema);
- const topNodes = useTypedSelector(selectTopNodesByLoad);
const columns = getTopNodesByLoadColumns(additionalNodesProps?.getNodeRef);
- const fetchNodes = React.useCallback(
- (isBackground: boolean) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
-
- dispatch(getTopNodesByLoad({tenant: path}));
- },
- [dispatch, path],
+ const {currentData, isFetching, error} = topNodesApi.useGetTopNodesQuery(
+ {tenant: path, sortValue: 'LoadAverage'},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
- useAutofetcher(fetchNodes, [fetchNodes], autorefresh);
+ const loading = isFetching && currentData === undefined;
+ const topNodes = currentData;
const title = getSectionTitle({
entity: i18n('nodes'),
@@ -62,7 +43,6 @@ export function TopNodesByLoad({path, additionalNodesProps}: TopNodesByLoadProps
columns={columns}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
emptyDataMessage={i18n('top-nodes.empty-data')}
/>
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx
index 86d7b75f9..0eeb7e14a 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx
@@ -10,11 +10,9 @@ import {
TENANT_PAGES_IDS,
TENANT_QUERY_TABS_ID,
} from '../../../../../store/reducers/tenant/constants';
-import {
- fetchTenantOverviewTopQueries,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries';
-import {useAutofetcher, useTypedDispatch, useTypedSelector} from '../../../../../utils/hooks';
+import {topQueriesApi} from '../../../../../store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useTypedDispatch, useTypedSelector} from '../../../../../utils/hooks';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {getTenantOverviewTopQueriesColumns} from '../../TopQueries/getTopQueriesColumns';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
@@ -33,27 +31,16 @@ export function TopQueries({path}: TopQueriesProps) {
const query = parseQuery(location);
const {autorefresh} = useTypedSelector((state) => state.schema);
-
- const {
- loading,
- wasLoaded,
- error,
- data: {result: data = undefined} = {},
- } = useTypedSelector((state) => state.tenantOverviewTopQueries);
const columns = getTenantOverviewTopQueriesColumns();
- useAutofetcher(
- (isBackground) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
-
- dispatch(fetchTenantOverviewTopQueries(path));
- },
- [dispatch, path],
- autorefresh,
+ const {currentData, isFetching, error} = topQueriesApi.useGetTopQueriesQuery(
+ {database: path},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
+ const loading = isFetching && currentData === undefined;
+ const {result: data} = currentData || {};
+
const handleRowClick = React.useCallback(
(row: any) => {
const {QueryText: input} = row;
@@ -89,7 +76,6 @@ export function TopQueries({path}: TopQueriesProps) {
onRowClick={handleRowClick}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
tableClassNameModifiers={{'top-queries': true}}
/>
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx
index 5cd9bff72..8a6548e53 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx
@@ -2,11 +2,9 @@ import {useLocation} from 'react-router';
import {parseQuery} from '../../../../../routes';
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
-import {
- sendTenantOverviewTopShardsQuery,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/topShards/tenantOverviewTopShards';
-import {useAutofetcher, useTypedDispatch, useTypedSelector} from '../../../../../utils/hooks';
+import {topShardsApi} from '../../../../../store/reducers/tenantOverview/topShards/tenantOverviewTopShards';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useTypedSelector} from '../../../../../utils/hooks';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {getTopShardsColumns} from '../../TopShards/getTopShardsColumns';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
@@ -18,31 +16,20 @@ interface TopShardsProps {
}
export const TopShards = ({path}: TopShardsProps) => {
- const dispatch = useTypedDispatch();
const location = useLocation();
const query = parseQuery(location);
const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema);
- const {
- loading,
- data: {result: data = undefined} = {},
- error,
- wasLoaded,
- } = useTypedSelector((state) => state.tenantOverviewTopShards);
-
- useAutofetcher(
- (isBackground) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
- dispatch(sendTenantOverviewTopShardsQuery(path, currentSchemaPath));
- },
- [dispatch, path, currentSchemaPath],
- autorefresh,
+ const {currentData, isFetching, error} = topShardsApi.useGetTopShardsQuery(
+ {database: path, path: currentSchemaPath},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
+ const loading = isFetching && currentData === undefined;
+ const {result: data} = currentData || {};
+
const columns = getTopShardsColumns(path, location);
const title = getSectionTitle({
@@ -60,7 +47,6 @@ export const TopShards = ({path}: TopShardsProps) => {
columns={columns}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
tableClassNameModifiers={{'top-queries': true}}
/>
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx
index bd47cf5e7..3e4634855 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.tsx
@@ -1,18 +1,8 @@
-import React from 'react';
-
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
-import {
- getTopNodesByMemory,
- selectTopNodesByMemory,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory';
+import {topNodesApi} from '../../../../../store/reducers/tenantOverview/topNodes/topNodes';
import type {AdditionalNodesProps} from '../../../../../types/additionalProps';
-import {
- useAutofetcher,
- useSearchQuery,
- useTypedDispatch,
- useTypedSelector,
-} from '../../../../../utils/hooks';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useSearchQuery, useTypedSelector} from '../../../../../utils/hooks';
import {getTopNodesByMemoryColumns} from '../../../../Nodes/getNodesColumns';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
@@ -25,29 +15,20 @@ interface TopNodesByMemoryProps {
}
export function TopNodesByMemory({path, additionalNodesProps}: TopNodesByMemoryProps) {
- const dispatch = useTypedDispatch();
-
const query = useSearchQuery();
- const {wasLoaded, loading, error} = useTypedSelector((state) => state.topNodesByMemory);
const {autorefresh} = useTypedSelector((state) => state.schema);
- const topNodes = useTypedSelector(selectTopNodesByMemory);
const columns = getTopNodesByMemoryColumns({
getNodeRef: additionalNodesProps?.getNodeRef,
});
- const fetchNodes = React.useCallback(
- (isBackground: boolean) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
-
- dispatch(getTopNodesByMemory({tenant: path}));
- },
- [dispatch, path],
+ const {currentData, isFetching, error} = topNodesApi.useGetTopNodesQuery(
+ {tenant: path, sortValue: 'Memory'},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
- useAutofetcher(fetchNodes, [fetchNodes], autorefresh);
+ const loading = isFetching && currentData === undefined;
+ const topNodes = currentData;
const title = getSectionTitle({
entity: i18n('nodes'),
@@ -64,7 +45,6 @@ export function TopNodesByMemory({path, additionalNodesProps}: TopNodesByMemoryP
columns={columns}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
emptyDataMessage={i18n('top-nodes.empty-data')}
/>
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx
index 49215a9fd..443cc1d11 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx
@@ -1,14 +1,12 @@
-import React from 'react';
-
import {Loader} from '@gravity-ui/uikit';
import {EntityStatus} from '../../../../components/EntityStatus/EntityStatus';
import {TENANT_METRICS_TABS_IDS} from '../../../../store/reducers/tenant/constants';
-import {getTenantInfo, setDataWasNotLoaded} from '../../../../store/reducers/tenant/tenant';
+import {tenantApi} from '../../../../store/reducers/tenant/tenant';
import {calculateTenantMetrics} from '../../../../store/reducers/tenants/utils';
import type {AdditionalNodesProps, AdditionalTenantsProps} from '../../../../types/additionalProps';
-import {TENANT_DEFAULT_TITLE} from '../../../../utils/constants';
-import {useAutofetcher, useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
+import {DEFAULT_POLLING_INTERVAL, TENANT_DEFAULT_TITLE} from '../../../../utils/constants';
+import {useTypedSelector} from '../../../../utils/hooks';
import {mapDatabaseTypeToDBName} from '../../utils/schema';
import {DefaultOverviewContent} from './DefaultOverviewContent/DefaultOverviewContent';
@@ -33,14 +31,7 @@ export function TenantOverview({
additionalTenantProps,
additionalNodesProps,
}: TenantOverviewProps) {
- const dispatch = useTypedDispatch();
-
- const {
- tenant,
- loading: tenantLoading,
- wasLoaded: tenantWasLoaded,
- metricsTab,
- } = useTypedSelector((state) => state.tenant);
+ const {metricsTab} = useTypedSelector((state) => state.tenant);
const {autorefresh} = useTypedSelector((state) => state.schema);
const {
@@ -52,24 +43,13 @@ export function TenantOverview({
refetch: fetchHealthcheck,
} = useHealthcheck(tenantName, {autorefresh});
- const fetchTenant = React.useCallback(
- (isBackground = true) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
- dispatch(getTenantInfo({path: tenantName}));
- },
- [dispatch, tenantName],
- );
-
- useAutofetcher(
- (isBackground) => {
- fetchTenant(isBackground);
+ const {currentData: tenant, isFetching} = tenantApi.useGetTenantInfoQuery(
+ {path: tenantName},
+ {
+ pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0,
},
- [fetchTenant],
- autorefresh,
);
-
+ const tenantLoading = isFetching && tenant === undefined;
const {Name, Type, Overall} = tenant || {};
const tenantType = mapDatabaseTypeToDBName(Type);
@@ -84,7 +64,7 @@ export function TenantOverview({
memoryStats,
blobStorageStats,
tabletStorageStats,
- } = calculateTenantMetrics(tenant);
+ } = calculateTenantMetrics(tenant ?? undefined);
const storageMetrics = {
blobStorageUsed: blobStorage,
@@ -133,7 +113,7 @@ export function TenantOverview({
}
};
- if (tenantLoading && !tenantWasLoaded) {
+ if (tenantLoading) {
return (
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx
index 994789bdc..03015a8ce 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.tsx
@@ -5,7 +5,6 @@ import type {DataTableProps} from '@gravity-ui/react-data-table';
import {ResponseError} from '../../../../components/Errors/ResponseError';
import {TableSkeleton} from '../../../../components/TableSkeleton/TableSkeleton';
-import type {IResponseError} from '../../../../types/api/error';
import {
TENANT_OVERVIEW_TABLES_LIMIT,
TENANT_OVERVIEW_TABLES_SETTINGS,
@@ -16,8 +15,7 @@ import {b} from './utils';
interface TenantOverviewTableLayoutProps
extends Omit, 'theme'> {
title: React.ReactNode;
loading?: boolean;
- wasLoaded?: boolean;
- error?: IResponseError;
+ error?: unknown;
tableClassNameModifiers?: {
[name: string]: string | boolean | undefined;
};
@@ -27,7 +25,6 @@ export function TenantOverviewTableLayout({
title,
error,
loading,
- wasLoaded,
tableClassNameModifiers = {},
...props
}: TenantOverviewTableLayoutProps) {
@@ -36,7 +33,7 @@ export function TenantOverviewTableLayout({
return ;
}
- if (loading && !wasLoaded) {
+ if (loading) {
return ;
}
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.tsx
index 0f89150b2..7ece61bae 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.tsx
@@ -1,17 +1,7 @@
-import React from 'react';
-
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
-import {
- getTopStorageGroups,
- selectTopStorageGroups,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/topStorageGroups/topStorageGroups';
-import {
- useAutofetcher,
- useSearchQuery,
- useTypedDispatch,
- useTypedSelector,
-} from '../../../../../utils/hooks';
+import {topStorageGroupsApi} from '../../../../../store/reducers/tenantOverview/topStorageGroups/topStorageGroups';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useSearchQuery, useTypedSelector} from '../../../../../utils/hooks';
import {getStorageTopGroupsColumns} from '../../../../Storage/StorageGroups/getStorageGroupsColumns';
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
@@ -23,28 +13,18 @@ interface TopGroupsProps {
}
export function TopGroups({tenant}: TopGroupsProps) {
- const dispatch = useTypedDispatch();
-
const query = useSearchQuery();
const {autorefresh} = useTypedSelector((state) => state.schema);
- const {loading, wasLoaded, error} = useTypedSelector((state) => state.topStorageGroups);
- const topGroups = useTypedSelector(selectTopStorageGroups);
const columns = getStorageTopGroupsColumns();
- const fetchData = React.useCallback(
- (isBackground: boolean) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
-
- dispatch(getTopStorageGroups({tenant}));
- },
- [dispatch, tenant],
+ const {currentData, isFetching, error} = topStorageGroupsApi.useGetTopStorageGroupsQuery(
+ {tenant},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
-
- useAutofetcher(fetchData, [fetchData], autorefresh);
+ const loading = isFetching && currentData === undefined;
+ const topGroups = currentData;
const title = getSectionTitle({
entity: i18n('groups'),
@@ -61,7 +41,6 @@ export function TopGroups({tenant}: TopGroupsProps) {
columns={columns}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
/>
);
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx
index 839fdf4c5..f0123e904 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx
@@ -4,13 +4,11 @@ import {useLocation} from 'react-router';
import {CellWithPopover} from '../../../../../components/CellWithPopover/CellWithPopover';
import {LinkToSchemaObject} from '../../../../../components/LinkToSchemaObject/LinkToSchemaObject';
-import {
- fetchTopTables,
- setDataWasNotLoaded,
-} from '../../../../../store/reducers/tenantOverview/executeTopTables/executeTopTables';
+import {topTablesApi} from '../../../../../store/reducers/tenantOverview/executeTopTables/executeTopTables';
import type {KeyValueRow} from '../../../../../types/api/query';
import {formatBytes, getSizeWithSignificantDigits} from '../../../../../utils/bytesParsers';
-import {useAutofetcher, useTypedDispatch, useTypedSelector} from '../../../../../utils/hooks';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../../utils/constants';
+import {useTypedSelector} from '../../../../../utils/hooks';
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
import {getSectionTitle} from '../getSectionTitle';
import i18n from '../i18n';
@@ -22,29 +20,17 @@ interface TopTablesProps {
}
export function TopTables({path}: TopTablesProps) {
- const dispatch = useTypedDispatch();
const location = useLocation();
const {autorefresh} = useTypedSelector((state) => state.schema);
- const {
- loading,
- wasLoaded,
- error,
- data: {result: data = undefined} = {},
- } = useTypedSelector((state) => state.executeTopTables);
-
- useAutofetcher(
- (isBackground) => {
- if (!isBackground) {
- dispatch(setDataWasNotLoaded());
- }
-
- dispatch(fetchTopTables(path));
- },
- [dispatch, path],
- autorefresh,
+ const {currentData, error, isFetching} = topTablesApi.useGetTopTablesQuery(
+ {path},
+ {pollingInterval: autorefresh ? DEFAULT_POLLING_INTERVAL : 0},
);
+ const loading = isFetching && currentData === undefined;
+
+ const {result: data} = currentData || {};
const formatSize = (value?: number) => {
const size = getSizeWithSignificantDigits(data?.length ? Number(data[0].Size) : 0, 0);
@@ -84,7 +70,6 @@ export function TopTables({path}: TopTablesProps) {
columns={columns}
title={title}
loading={loading}
- wasLoaded={wasLoaded}
error={error}
/>
);
diff --git a/src/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts b/src/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts
index 43331c703..4c88f1643 100644
--- a/src/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts
+++ b/src/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts
@@ -1,4 +1,3 @@
-import {DEFAULT_POLLING_INTERVAL} from '../../../../lib';
import {
healthcheckApi,
selectIssuesStatistics,
@@ -7,6 +6,7 @@ import {
import type {IssuesTree} from '../../../../store/reducers/healthcheckInfo/types';
import {SelfCheckResult} from '../../../../types/api/healthcheck';
import type {StatusFlag} from '../../../../types/api/healthcheck';
+import {DEFAULT_POLLING_INTERVAL} from '../../../../utils/constants';
import {useTypedSelector} from '../../../../utils/hooks';
interface HealthcheckParams {
diff --git a/src/services/api.ts b/src/services/api.ts
index 0fd42a3e9..f5e283bc7 100644
--- a/src/services/api.ts
+++ b/src/services/api.ts
@@ -83,7 +83,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
cluster_name: clusterName,
});
}
- getTenantInfo({path}: {path: string}, {concurrentId}: AxiosOptions = {}) {
+ getTenantInfo({path}: {path: string}, {concurrentId, signal}: AxiosOptions = {}) {
return this.get(
this.getPath('/viewer/json/tenantinfo'),
{
@@ -91,7 +91,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
tablets: true,
storage: true,
},
- {concurrentId: concurrentId || `getTenantInfo|${path}`},
+ {concurrentId: concurrentId || `getTenantInfo|${path}`, requestConfig: {signal}},
);
}
getNodes(
@@ -137,7 +137,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
sortValue,
...params
}: StorageApiRequestParams,
- {concurrentId}: AxiosOptions = {},
+ {concurrentId, signal}: AxiosOptions = {},
) {
const sort = prepareSortValue(sortValue, sortOrder);
@@ -152,7 +152,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
sort,
...params,
},
- {concurrentId},
+ {concurrentId, requestConfig: {signal}},
);
}
getPdiskInfo(nodeId: string | number, pdiskId: string | number) {
@@ -316,7 +316,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
schema?: Schema;
syntax?: QuerySyntax;
},
- {concurrentId}: AxiosOptions = {},
+ {concurrentId, signal}: AxiosOptions = {},
) {
// Time difference to ensure that timeout from ui will be shown rather than backend error
const uiTimeout = 9 * 60 * 1000;
@@ -342,6 +342,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
{
concurrentId,
timeout: uiTimeout,
+ requestConfig: {signal},
},
);
}
diff --git a/src/store/reducers/index.ts b/src/store/reducers/index.ts
index 44b235d13..f256d23ed 100644
--- a/src/store/reducers/index.ts
+++ b/src/store/reducers/index.ts
@@ -33,13 +33,6 @@ import tablet from './tablet';
import tablets from './tablets';
import tabletsFilters from './tabletsFilters';
import tenant from './tenant/tenant';
-import executeTopTables from './tenantOverview/executeTopTables/executeTopTables';
-import {topNodesByCpu} from './tenantOverview/topNodesByCpu/topNodesByCpu';
-import {topNodesByLoad} from './tenantOverview/topNodesByLoad/topNodesByLoad';
-import {topNodesByMemory} from './tenantOverview/topNodesByMemory/topNodesByMemory';
-import {tenantOverviewTopQueries} from './tenantOverview/topQueries/tenantOverviewTopQueries';
-import {tenantOverviewTopShards} from './tenantOverview/topShards/tenantOverviewTopShards';
-import topStorageGroups from './tenantOverview/topStorageGroups/topStorageGroups';
import tenants from './tenants/tenants';
import tooltip from './tooltip';
import topic from './topic';
@@ -49,13 +42,9 @@ export const rootReducer = {
[api.reducerPath]: api.reducer,
singleClusterMode,
nodes,
- topNodesByLoad,
- topNodesByCpu,
- topNodesByMemory,
cluster,
tenant,
storage,
- topStorageGroups,
node,
tooltip,
tablets,
@@ -79,10 +68,7 @@ export const rootReducer = {
describe,
schemaAcl,
executeTopQueries,
- executeTopTables,
- tenantOverviewTopQueries,
shardsWorkload,
- tenantOverviewTopShards,
hotKeys,
authentication,
header,
diff --git a/src/store/reducers/tenant/tenant.ts b/src/store/reducers/tenant/tenant.ts
index b10d1ef83..5d465e818 100644
--- a/src/store/reducers/tenant/tenant.ts
+++ b/src/store/reducers/tenant/tenant.ts
@@ -1,10 +1,9 @@
-import type {Reducer} from '@reduxjs/toolkit';
+import {createSlice} from '@reduxjs/toolkit';
+import type {PayloadAction} from '@reduxjs/toolkit';
-import type {TTenant} from '../../../types/api/tenant';
-import {createApiRequest, createRequestActionTypes} from '../../utils';
+import {api} from '../api';
import type {
- TenantAction,
TenantDiagnosticsTab,
TenantMetricsTab,
TenantPage,
@@ -13,159 +12,44 @@ import type {
TenantSummaryTab,
} from './types';
-export const FETCH_TENANT = createRequestActionTypes('tenant', 'FETCH_TENANT');
-
-const SET_TOP_LEVEL_TAB = 'tenant/SET_TOP_LEVEL_TAB';
-const SET_QUERY_TAB = 'tenant/SET_QUERY_TAB';
-const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
-const SET_SUMMARY_TAB = 'tenant/SET_SUMMARY_TAB';
-const SET_METRICS_TAB = 'tenant/SET_METRICS_TAB';
-const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
-const SET_DATA_WAS_NOT_LOADED = 'tenant/SET_DATA_WAS_NOT_LOADED';
-
-// Tenant diagnostics tab content was requested twice,
-// because requests were sent before state was set as loading and after tenant data is fully loaded
-// So tenant data is considered loading from the start, there is no attempt to load tab content
-// TODO: try fix with 'display: none' for tenant diagnostics tab content while tenant data loading,
-// but with parallel (not sequent) data requests
-const initialState = {loading: true, wasLoaded: false};
-
-const tenantReducer: Reducer = (state = initialState, action) => {
- switch (action.type) {
- case FETCH_TENANT.REQUEST: {
- return {
- ...state,
- loading: true,
- };
- }
-
- case FETCH_TENANT.SUCCESS: {
- return {
- ...state,
- tenant: action.data,
- loading: false,
- wasLoaded: true,
- error: undefined,
- };
- }
-
- case FETCH_TENANT.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
-
- return {
- ...state,
- error: action.error,
- loading: false,
- wasLoaded: true,
- };
- }
-
- case CLEAR_TENANT: {
- return {
- ...state,
- tenant: undefined,
- loading: true,
- };
- }
-
- case SET_TOP_LEVEL_TAB: {
- return {
- ...state,
- tenantPage: action.data,
- };
- }
- case SET_QUERY_TAB: {
- return {
- ...state,
- queryTab: action.data,
- };
- }
- case SET_DIAGNOSTICS_TAB: {
- return {
- ...state,
- diagnosticsTab: action.data,
- };
- }
- case SET_SUMMARY_TAB: {
- return {
- ...state,
- summaryTab: action.data,
- };
- }
- case SET_METRICS_TAB: {
- return {
- ...state,
- metricsTab: action.data,
- };
- }
-
- case SET_DATA_WAS_NOT_LOADED: {
- return {
- ...state,
- wasLoaded: false,
- };
- }
-
- default:
- return state;
- }
-};
-
-export const getTenantInfo = ({path}: {path: string}) => {
- return createApiRequest({
- request: window.api.getTenantInfo({path}, {concurrentId: 'getTenantInfo'}),
- actions: FETCH_TENANT,
- dataHandler: (tenantData): TTenant | undefined => {
- return tenantData.TenantInfo?.[0];
+const slice = createSlice({
+ name: 'tenant',
+ initialState: {} as TenantState,
+ reducers: {
+ setTenantPage: (state, action: PayloadAction) => {
+ state.tenantPage = action.payload;
},
- });
-};
-
-export const clearTenant = () => {
- return {type: CLEAR_TENANT} as const;
-};
-
-export function setTenantPage(page: TenantPage) {
- return {
- type: SET_TOP_LEVEL_TAB,
- data: page,
- } as const;
-}
-
-export function setQueryTab(tab: TenantQueryTab) {
- return {
- type: SET_QUERY_TAB,
- data: tab,
- } as const;
-}
-
-export function setDiagnosticsTab(tab: TenantDiagnosticsTab) {
- return {
- type: SET_DIAGNOSTICS_TAB,
- data: tab,
- } as const;
-}
-
-export function setSummaryTab(tab: TenantSummaryTab) {
- return {
- type: SET_SUMMARY_TAB,
- data: tab,
- } as const;
-}
-
-export function setMetricsTab(tab: TenantMetricsTab) {
- return {
- type: SET_METRICS_TAB,
- data: tab,
- } as const;
-}
-
-export const setDataWasNotLoaded = () => {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-};
-
-export default tenantReducer;
+ setQueryTab: (state, action: PayloadAction) => {
+ state.queryTab = action.payload;
+ },
+ setDiagnosticsTab: (state, action: PayloadAction) => {
+ state.diagnosticsTab = action.payload;
+ },
+ setSummaryTab: (state, action: PayloadAction) => {
+ state.summaryTab = action.payload;
+ },
+ setMetricsTab: (state, action: PayloadAction) => {
+ state.metricsTab = action.payload;
+ },
+ },
+});
+
+export default slice.reducer;
+export const {setTenantPage, setQueryTab, setDiagnosticsTab, setSummaryTab, setMetricsTab} =
+ slice.actions;
+
+export const tenantApi = api.injectEndpoints({
+ endpoints: (builder) => ({
+ getTenantInfo: builder.query({
+ queryFn: async ({path}: {path: string}, {signal}) => {
+ try {
+ const tenantData = await window.api.getTenantInfo({path}, {signal});
+ return {data: tenantData.TenantInfo?.[0] ?? null};
+ } catch (error) {
+ return {error};
+ }
+ },
+ providesTags: ['All'],
+ }),
+ }),
+});
diff --git a/src/store/reducers/tenant/types.ts b/src/store/reducers/tenant/types.ts
index 198921dc5..d64399073 100644
--- a/src/store/reducers/tenant/types.ts
+++ b/src/store/reducers/tenant/types.ts
@@ -1,7 +1,4 @@
-import type {IResponseError} from '../../../types/api/error';
-import type {TTenant} from '../../../types/api/tenant';
import type {ValueOf} from '../../../types/common';
-import type {ApiRequestAction} from '../../utils';
import type {
TENANT_DIAGNOSTICS_TABS_IDS,
@@ -10,16 +7,6 @@ import type {
TENANT_QUERY_TABS_ID,
TENANT_SUMMARY_TABS_IDS,
} from './constants';
-import type {
- FETCH_TENANT,
- clearTenant,
- setDataWasNotLoaded,
- setDiagnosticsTab,
- setMetricsTab,
- setQueryTab,
- setSummaryTab,
- setTenantPage,
-} from './tenant';
export type TenantPage = ValueOf;
@@ -29,23 +16,9 @@ export type TenantSummaryTab = ValueOf;
export type TenantMetricsTab = ValueOf;
export interface TenantState {
- loading: boolean;
- wasLoaded: boolean;
tenantPage?: TenantPage;
queryTab?: TenantQueryTab;
diagnosticsTab?: TenantDiagnosticsTab;
summaryTab?: TenantSummaryTab;
metricsTab?: TenantMetricsTab;
- tenant?: TTenant;
- error?: IResponseError;
}
-
-export type TenantAction =
- | ApiRequestAction
- | ReturnType
- | ReturnType
- | ReturnType
- | ReturnType
- | ReturnType
- | ReturnType
- | ReturnType;
diff --git a/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts b/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts
index 9f0faa9a0..8624970be 100644
--- a/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts
+++ b/src/store/reducers/tenantOverview/executeTopTables/executeTopTables.ts
@@ -1,18 +1,6 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
-
-import type {TopTablesAction, TopTablesState} from './types';
-
-export const FETCH_TOP_TABLES = createRequestActionTypes('top-tables', 'FETCH_TOP_TABLES');
-const SET_DATA_WAS_NOT_LOADED = 'top-tables/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: false,
- wasLoaded: false,
-};
+import {api} from '../../api';
const getQueryText = (path: string) => {
return `
@@ -25,70 +13,26 @@ GROUP BY Path
`;
};
-const executeTopTables: Reducer = (
- state = initialState,
- action,
-) => {
- switch (action.type) {
- case FETCH_TOP_TABLES.REQUEST: {
- return {
- ...state,
- loading: true,
- error: undefined,
- };
- }
- case FETCH_TOP_TABLES.SUCCESS: {
- return {
- ...state,
- data: action.data,
- loading: false,
- error: undefined,
- wasLoaded: true,
- };
- }
- // 401 Unauthorized error is handled by GenericAPI
- case FETCH_TOP_TABLES.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
- return {
- ...state,
- error: action.error || 'Unauthorized',
- loading: false,
- };
- }
- case SET_DATA_WAS_NOT_LOADED:
- return {
- ...state,
- wasLoaded: false,
- };
- default:
- return state;
- }
-};
-
-export const fetchTopTables = (database: string) => {
- return createApiRequest({
- request: window.api.sendQuery(
- {
- schema: 'modern',
- query: getQueryText(database),
- database,
- action: 'execute-scan',
- },
- {
- concurrentId: 'executeTopTables',
+export const topTablesApi = api.injectEndpoints({
+ endpoints: (builder) => ({
+ getTopTables: builder.query({
+ queryFn: async ({path}: {path: string}, {signal}) => {
+ try {
+ const data = await window.api.sendQuery(
+ {
+ schema: 'modern',
+ query: getQueryText(path),
+ database: path,
+ action: 'execute-scan',
+ },
+ {signal},
+ );
+ return {data: parseQueryAPIExecuteResponse(data)};
+ } catch (error) {
+ return {error: error || 'Unauthorized'};
+ }
},
- ),
- actions: FETCH_TOP_TABLES,
- dataHandler: parseQueryAPIExecuteResponse,
- });
-};
-
-export function setDataWasNotLoaded() {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-}
-
-export default executeTopTables;
+ providesTags: ['All'],
+ }),
+ }),
+});
diff --git a/src/store/reducers/tenantOverview/executeTopTables/types.ts b/src/store/reducers/tenantOverview/executeTopTables/types.ts
deleted file mode 100644
index 5cad8e605..000000000
--- a/src/store/reducers/tenantOverview/executeTopTables/types.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
-import type {ApiRequestAction} from '../../../utils';
-
-import type {FETCH_TOP_TABLES, setDataWasNotLoaded} from './executeTopTables';
-
-export interface TopTablesState {
- loading: boolean;
- wasLoaded: boolean;
- data?: IQueryResult;
- error?: QueryErrorResponse;
-}
-
-export type TopTablesAction =
- | ApiRequestAction
- | ReturnType;
diff --git a/src/store/reducers/tenantOverview/topNodes/topNodes.ts b/src/store/reducers/tenantOverview/topNodes/topNodes.ts
new file mode 100644
index 000000000..036327f6c
--- /dev/null
+++ b/src/store/reducers/tenantOverview/topNodes/topNodes.ts
@@ -0,0 +1,29 @@
+import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
+import {api} from '../../api';
+import type {NodesApiRequestParams} from '../../nodes/types';
+import {prepareNodesData} from '../../nodes/utils';
+
+export const topNodesApi = api.injectEndpoints({
+ endpoints: (builder) => ({
+ getTopNodes: builder.query({
+ queryFn: async (params: NodesApiRequestParams, {signal}) => {
+ try {
+ const data = await window.api.getNodes(
+ {
+ type: 'any',
+ sortOrder: -1,
+ // sortValue: 'CPU',
+ limit: TENANT_OVERVIEW_TABLES_LIMIT,
+ ...params,
+ },
+ {signal},
+ );
+ return {data: prepareNodesData(data).Nodes};
+ } catch (error) {
+ return {error};
+ }
+ },
+ providesTags: ['All'],
+ }),
+ }),
+});
diff --git a/src/store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu.ts b/src/store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu.ts
deleted file mode 100644
index fafcfdb20..000000000
--- a/src/store/reducers/tenantOverview/topNodesByCpu/topNodesByCpu.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
-import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
-import type {NodesApiRequestParams} from '../../nodes/types';
-import {prepareNodesData} from '../../nodes/utils';
-
-import type {TopNodesByCpuAction, TopNodesByCpuState, TopPoolsStateSlice} from './types';
-
-export const FETCH_TOP_NODES_BY_CPU = createRequestActionTypes(
- 'topNodesByCpu',
- 'FETCH_TOP_NODES_BY_CPU',
-);
-const SET_DATA_WAS_NOT_LOADED = 'topNodesByCpu/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: false,
- wasLoaded: false,
-};
-
-export const topNodesByCpu: Reducer = (
- state = initialState,
- action,
-) => {
- switch (action.type) {
- case FETCH_TOP_NODES_BY_CPU.REQUEST: {
- return {
- ...state,
- loading: true,
- };
- }
- case FETCH_TOP_NODES_BY_CPU.SUCCESS: {
- return {
- ...state,
- data: action.data?.Nodes,
- loading: false,
- wasLoaded: true,
- error: undefined,
- };
- }
- case FETCH_TOP_NODES_BY_CPU.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
-
- return {
- ...state,
- error: action.error,
- loading: false,
- };
- }
- case SET_DATA_WAS_NOT_LOADED: {
- return {
- ...state,
- wasLoaded: false,
- };
- }
- default:
- return state;
- }
-};
-
-const concurrentId = 'getTopNodeByCpu';
-
-export function getTopNodesByCpu({
- type = 'any',
- sortOrder = -1,
- sortValue = 'CPU',
- limit = TENANT_OVERVIEW_TABLES_LIMIT,
- ...params
-}: NodesApiRequestParams) {
- return createApiRequest({
- request: window.api.getNodes(
- {type, sortOrder, sortValue, limit, ...params},
- {concurrentId},
- ),
- actions: FETCH_TOP_NODES_BY_CPU,
- dataHandler: prepareNodesData,
- });
-}
-
-export const selectTopNodesByCpu = (state: TopPoolsStateSlice) => state.topNodesByCpu.data;
-
-export const setDataWasNotLoaded = () => {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-};
diff --git a/src/store/reducers/tenantOverview/topNodesByCpu/types.ts b/src/store/reducers/tenantOverview/topNodesByCpu/types.ts
deleted file mode 100644
index 114564e16..000000000
--- a/src/store/reducers/tenantOverview/topNodesByCpu/types.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type {IResponseError} from '../../../../types/api/error';
-import type {ApiRequestAction} from '../../../utils';
-import type {NodesPreparedEntity} from '../../nodes/types';
-
-import type {FETCH_TOP_NODES_BY_CPU, setDataWasNotLoaded} from './topNodesByCpu';
-
-export interface TopNodesByCpuState {
- loading: boolean;
- wasLoaded: boolean;
- data?: NodesPreparedEntity[];
- error?: IResponseError;
-}
-
-export interface TopNodesByCpuHandledResponse {
- Nodes?: NodesPreparedEntity[];
-}
-
-type TopNodesByCpuApiRequestAction = ApiRequestAction<
- typeof FETCH_TOP_NODES_BY_CPU,
- TopNodesByCpuHandledResponse,
- IResponseError
->;
-
-export type TopNodesByCpuAction =
- | TopNodesByCpuApiRequestAction
- | ReturnType;
-
-export interface TopPoolsStateSlice {
- topNodesByCpu: TopNodesByCpuState;
-}
diff --git a/src/store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad.ts b/src/store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad.ts
deleted file mode 100644
index 7a0ad437b..000000000
--- a/src/store/reducers/tenantOverview/topNodesByLoad/topNodesByLoad.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
-import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
-import type {NodesApiRequestParams} from '../../nodes/types';
-import {prepareNodesData} from '../../nodes/utils';
-
-import type {TopNodesByLoadAction, TopNodesByLoadState, TopNodesByLoadStateSlice} from './types';
-
-export const FETCH_TOP_NODES_BY_LOAD = createRequestActionTypes(
- 'topNodesByLoad',
- 'FETCH_TOP_NODES_BY_LOAD',
-);
-const SET_DATA_WAS_NOT_LOADED = 'topNodesByLoad/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: false,
- wasLoaded: false,
-};
-
-export const topNodesByLoad: Reducer = (
- state = initialState,
- action,
-) => {
- switch (action.type) {
- case FETCH_TOP_NODES_BY_LOAD.REQUEST: {
- return {
- ...state,
- loading: true,
- };
- }
- case FETCH_TOP_NODES_BY_LOAD.SUCCESS: {
- return {
- ...state,
- data: action.data?.Nodes,
- loading: false,
- wasLoaded: true,
- error: undefined,
- };
- }
- case FETCH_TOP_NODES_BY_LOAD.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
-
- return {
- ...state,
- error: action.error,
- loading: false,
- };
- }
- case SET_DATA_WAS_NOT_LOADED: {
- return {
- ...state,
- wasLoaded: false,
- };
- }
- default:
- return state;
- }
-};
-
-const concurrentId = 'getTopNodesByLoad';
-
-export function getTopNodesByLoad({
- type = 'any',
- sortOrder = -1,
- sortValue = 'LoadAverage',
- limit = TENANT_OVERVIEW_TABLES_LIMIT,
- ...params
-}: NodesApiRequestParams) {
- return createApiRequest({
- request: window.api.getNodes(
- {type, sortOrder, sortValue, limit, ...params},
- {concurrentId},
- ),
- actions: FETCH_TOP_NODES_BY_LOAD,
- dataHandler: prepareNodesData,
- });
-}
-
-export const selectTopNodesByLoad = (state: TopNodesByLoadStateSlice) => state.topNodesByLoad.data;
-
-export const setDataWasNotLoaded = () => {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-};
diff --git a/src/store/reducers/tenantOverview/topNodesByLoad/types.ts b/src/store/reducers/tenantOverview/topNodesByLoad/types.ts
deleted file mode 100644
index 4044fceb0..000000000
--- a/src/store/reducers/tenantOverview/topNodesByLoad/types.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type {IResponseError} from '../../../../types/api/error';
-import type {ApiRequestAction} from '../../../utils';
-import type {NodesPreparedEntity} from '../../nodes/types';
-
-import type {FETCH_TOP_NODES_BY_LOAD, setDataWasNotLoaded} from './topNodesByLoad';
-
-export interface TopNodesByLoadState {
- loading: boolean;
- wasLoaded: boolean;
- data?: NodesPreparedEntity[];
- error?: IResponseError;
-}
-
-export interface TopNodesByLoadHandledResponse {
- Nodes?: NodesPreparedEntity[];
-}
-
-type TopNodesByLoadApiRequestAction = ApiRequestAction<
- typeof FETCH_TOP_NODES_BY_LOAD,
- TopNodesByLoadHandledResponse,
- IResponseError
->;
-
-export type TopNodesByLoadAction =
- | TopNodesByLoadApiRequestAction
- | ReturnType;
-
-export interface TopNodesByLoadStateSlice {
- topNodesByLoad: TopNodesByLoadState;
-}
diff --git a/src/store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory.ts b/src/store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory.ts
deleted file mode 100644
index 3f97dd3f2..000000000
--- a/src/store/reducers/tenantOverview/topNodesByMemory/topNodesByMemory.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
-import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
-import type {NodesApiRequestParams} from '../../nodes/types';
-import {prepareNodesData} from '../../nodes/utils';
-
-import type {TopNodesByMemoryAction, TopNodesByMemorySlice, TopNodesByMemoryState} from './types';
-
-export const FETCH_TOP_NODES_BY_MEMORY = createRequestActionTypes(
- 'topNodesByMemory',
- 'FETCH_TOP_NODES_BY_MEMORY',
-);
-const SET_DATA_WAS_NOT_LOADED = 'topNodesByMemory/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: false,
- wasLoaded: false,
-};
-
-export const topNodesByMemory: Reducer = (
- state = initialState,
- action,
-) => {
- switch (action.type) {
- case FETCH_TOP_NODES_BY_MEMORY.REQUEST: {
- return {
- ...state,
- loading: true,
- };
- }
- case FETCH_TOP_NODES_BY_MEMORY.SUCCESS: {
- return {
- ...state,
- data: action.data?.Nodes,
- loading: false,
- wasLoaded: true,
- error: undefined,
- };
- }
- case FETCH_TOP_NODES_BY_MEMORY.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
-
- return {
- ...state,
- error: action.error,
- loading: false,
- };
- }
- case SET_DATA_WAS_NOT_LOADED: {
- return {
- ...state,
- wasLoaded: false,
- };
- }
- default:
- return state;
- }
-};
-
-const concurrentId = 'getTopNodeByMemory';
-
-export function getTopNodesByMemory({
- type = 'any',
- sortOrder = -1,
- sortValue = 'Memory',
- limit = TENANT_OVERVIEW_TABLES_LIMIT,
- ...params
-}: NodesApiRequestParams) {
- return createApiRequest({
- request: window.api.getNodes(
- {type, sortOrder, sortValue, limit, ...params},
- {concurrentId},
- ),
- actions: FETCH_TOP_NODES_BY_MEMORY,
- dataHandler: prepareNodesData,
- });
-}
-
-export const selectTopNodesByMemory = (state: TopNodesByMemorySlice) => state.topNodesByMemory.data;
-
-export const setDataWasNotLoaded = () => {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-};
diff --git a/src/store/reducers/tenantOverview/topNodesByMemory/types.ts b/src/store/reducers/tenantOverview/topNodesByMemory/types.ts
deleted file mode 100644
index c052d212c..000000000
--- a/src/store/reducers/tenantOverview/topNodesByMemory/types.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type {IResponseError} from '../../../../types/api/error';
-import type {ApiRequestAction} from '../../../utils';
-import type {NodesPreparedEntity} from '../../nodes/types';
-
-import type {FETCH_TOP_NODES_BY_MEMORY, setDataWasNotLoaded} from './topNodesByMemory';
-
-export interface TopNodesByMemoryState {
- loading: boolean;
- wasLoaded: boolean;
- data?: NodesPreparedEntity[];
- error?: IResponseError;
-}
-
-export interface TopNodesByMemoryHandledResponse {
- Nodes?: NodesPreparedEntity[];
-}
-
-type TopNodesByMemoryApiRequestAction = ApiRequestAction<
- typeof FETCH_TOP_NODES_BY_MEMORY,
- TopNodesByMemoryHandledResponse,
- IResponseError
->;
-
-export type TopNodesByMemoryAction =
- | TopNodesByMemoryApiRequestAction
- | ReturnType;
-
-export interface TopNodesByMemorySlice {
- topNodesByMemory: TopNodesByMemoryState;
-}
diff --git a/src/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts b/src/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts
index 4b9d214f6..faa029d03 100644
--- a/src/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts
+++ b/src/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.ts
@@ -1,22 +1,6 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
-
-import type {TenantOverviewTopQueriesAction, TenantOverviewTopQueriesState} from './types';
-
-export const FETCH_TENANT_OVERVIEW_TOP_QUERIES = createRequestActionTypes(
- 'tenantOverviewTopQueries',
- 'FETCH_TOP_QUERIES',
-);
-const SET_DATA_WAS_NOT_LOADED = 'tenantOverviewTopQueries/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: false,
- wasLoaded: false,
- filters: {},
-};
+import {api} from '../../api';
const getQueryText = (path: string) => {
return `
@@ -29,64 +13,26 @@ LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT}
`;
};
-export const tenantOverviewTopQueries: Reducer<
- TenantOverviewTopQueriesState,
- TenantOverviewTopQueriesAction
-> = (state = initialState, action) => {
- switch (action.type) {
- case FETCH_TENANT_OVERVIEW_TOP_QUERIES.REQUEST: {
- return {
- ...state,
- loading: true,
- error: undefined,
- };
- }
- case FETCH_TENANT_OVERVIEW_TOP_QUERIES.SUCCESS: {
- return {
- ...state,
- data: action.data,
- loading: false,
- error: undefined,
- wasLoaded: true,
- };
- }
- // 401 Unauthorized error is handled by GenericAPI
- case FETCH_TENANT_OVERVIEW_TOP_QUERIES.FAILURE: {
- return {
- ...state,
- error: action.error || 'Unauthorized',
- loading: false,
- };
- }
- case SET_DATA_WAS_NOT_LOADED:
- return {
- ...state,
- wasLoaded: false,
- };
- default:
- return state;
- }
-};
-
-export const fetchTenantOverviewTopQueries = (database: string) =>
- createApiRequest({
- request: window.api.sendQuery(
- {
- schema: 'modern',
- query: getQueryText(database),
- database,
- action: 'execute-scan',
+export const topQueriesApi = api.injectEndpoints({
+ endpoints: (builder) => ({
+ getTopQueries: builder.query({
+ queryFn: async ({database}: {database: string}, {signal}) => {
+ try {
+ const data = await window.api.sendQuery(
+ {
+ schema: 'modern',
+ query: getQueryText(database),
+ database,
+ action: 'execute-scan',
+ },
+ {signal},
+ );
+ return {data: parseQueryAPIExecuteResponse(data)};
+ } catch (error) {
+ return {error: error || new Error('Unauthorized')};
+ }
},
- {
- concurrentId: 'executeTopQueries',
- },
- ),
- actions: FETCH_TENANT_OVERVIEW_TOP_QUERIES,
- dataHandler: parseQueryAPIExecuteResponse,
- });
-
-export function setDataWasNotLoaded() {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-}
+ providesTags: ['All'],
+ }),
+ }),
+});
diff --git a/src/store/reducers/tenantOverview/topQueries/types.ts b/src/store/reducers/tenantOverview/topQueries/types.ts
deleted file mode 100644
index f774501ed..000000000
--- a/src/store/reducers/tenantOverview/topQueries/types.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
-import type {ApiRequestAction} from '../../../utils';
-
-import type {
- FETCH_TENANT_OVERVIEW_TOP_QUERIES,
- setDataWasNotLoaded,
-} from './tenantOverviewTopQueries';
-
-export interface TenantOverviewTopQueriesState {
- loading: boolean;
- wasLoaded: boolean;
- data?: IQueryResult;
- error?: QueryErrorResponse;
-}
-
-export type TenantOverviewTopQueriesAction =
- | ApiRequestAction
- | ReturnType;
diff --git a/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts b/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts
index f2ae79680..78ce8240e 100644
--- a/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts
+++ b/src/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.ts
@@ -1,21 +1,6 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
import {parseQueryAPIExecuteResponse} from '../../../../utils/query';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
-
-import type {TenantOverviewTopShardsAction, TenantOverviewTopShardsState} from './types';
-
-export const FETCH_TENANT_OVERVIEW_TOP_SHARDS = createRequestActionTypes(
- 'tenantOverviewTopShards',
- 'FETCH_TENANT_OVERVIEW_TOP_SHARDS',
-);
-const SET_DATA_WAS_NOT_LOADED = 'tenantOverviewTopShards/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: false,
- wasLoaded: false,
-};
+import {api} from '../../api';
function createShardQuery(path: string, tenantName?: string) {
const pathSelect = tenantName
@@ -36,68 +21,26 @@ LIMIT ${TENANT_OVERVIEW_TABLES_LIMIT}`;
const queryAction = 'execute-scan';
-export const tenantOverviewTopShards: Reducer<
- TenantOverviewTopShardsState,
- TenantOverviewTopShardsAction
-> = (state = initialState, action) => {
- switch (action.type) {
- case FETCH_TENANT_OVERVIEW_TOP_SHARDS.REQUEST: {
- return {
- ...state,
- loading: true,
- error: undefined,
- };
- }
- case FETCH_TENANT_OVERVIEW_TOP_SHARDS.SUCCESS: {
- return {
- ...state,
- data: action.data,
- loading: false,
- error: undefined,
- wasLoaded: true,
- };
- }
- // 401 Unauthorized error is handled by GenericAPI
- case FETCH_TENANT_OVERVIEW_TOP_SHARDS.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
-
- return {
- ...state,
- error: action.error || 'Unauthorized',
- loading: false,
- };
- }
- case SET_DATA_WAS_NOT_LOADED:
- return {
- ...state,
- wasLoaded: false,
- };
- default:
- return state;
- }
-};
-
-export const sendTenantOverviewTopShardsQuery = (database: string, path = '') =>
- createApiRequest({
- request: window.api.sendQuery(
- {
- schema: 'modern',
- query: createShardQuery(path, database),
- database,
- action: queryAction,
- },
- {
- concurrentId: 'executeTopShards',
+export const topShardsApi = api.injectEndpoints({
+ endpoints: (builder) => ({
+ getTopShards: builder.query({
+ queryFn: async ({database, path = ''}: {database: string; path?: string}, {signal}) => {
+ try {
+ const data = await window.api.sendQuery(
+ {
+ schema: 'modern',
+ query: createShardQuery(path, database),
+ database,
+ action: queryAction,
+ },
+ {signal},
+ );
+ return {data: parseQueryAPIExecuteResponse(data)};
+ } catch (error) {
+ return {error: error || new Error('Unauthorized')};
+ }
},
- ),
- actions: FETCH_TENANT_OVERVIEW_TOP_SHARDS,
- dataHandler: parseQueryAPIExecuteResponse,
- });
-
-export function setDataWasNotLoaded() {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-}
+ providesTags: ['All'],
+ }),
+ }),
+});
diff --git a/src/store/reducers/tenantOverview/topShards/types.ts b/src/store/reducers/tenantOverview/topShards/types.ts
deleted file mode 100644
index 029c91644..000000000
--- a/src/store/reducers/tenantOverview/topShards/types.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
-import type {ApiRequestAction} from '../../../utils';
-
-import type {
- FETCH_TENANT_OVERVIEW_TOP_SHARDS,
- setDataWasNotLoaded,
-} from './tenantOverviewTopShards';
-
-export interface TenantOverviewTopShardsState {
- loading: boolean;
- wasLoaded: boolean;
- data?: IQueryResult;
- error?: QueryErrorResponse;
-}
-
-export type TenantOverviewTopShardsAction =
- | ApiRequestAction
- | ReturnType;
diff --git a/src/store/reducers/tenantOverview/topStorageGroups/topStorageGroups.ts b/src/store/reducers/tenantOverview/topStorageGroups/topStorageGroups.ts
index 39baf13d8..2205cc6ad 100644
--- a/src/store/reducers/tenantOverview/topStorageGroups/topStorageGroups.ts
+++ b/src/store/reducers/tenantOverview/topStorageGroups/topStorageGroups.ts
@@ -1,99 +1,32 @@
-import type {Reducer} from '@reduxjs/toolkit';
-
import {EVersion} from '../../../../types/api/storage';
import {TENANT_OVERVIEW_TABLES_LIMIT} from '../../../../utils/constants';
-import {createApiRequest, createRequestActionTypes} from '../../../utils';
+import {api} from '../../api';
import type {StorageApiRequestParams} from '../../storage/types';
-import type {
- TopStorageGroupsAction,
- TopStorageGroupsState,
- TopStorageGroupsStateSlice,
-} from './types';
import {prepareTopStorageGroupsResponse} from './utils';
-export const FETCH_TOP_STORAGE_GROUPS = createRequestActionTypes(
- 'topStorageGroups',
- 'FETCH_TOP_STORAGE_GROUPS',
-);
-
-const SET_DATA_WAS_NOT_LOADED = 'topStorageGroups/SET_DATA_WAS_NOT_LOADED';
-
-const initialState = {
- loading: true,
- wasLoaded: false,
-};
-
-const topStorageGroups: Reducer = (
- state = initialState,
- action,
-) => {
- switch (action.type) {
- case FETCH_TOP_STORAGE_GROUPS.REQUEST: {
- return {
- ...state,
- loading: true,
- };
- }
- case FETCH_TOP_STORAGE_GROUPS.SUCCESS: {
- return {
- ...state,
- data: action.data.groups,
- loading: false,
- wasLoaded: true,
- error: undefined,
- };
- }
- case FETCH_TOP_STORAGE_GROUPS.FAILURE: {
- if (action.error?.isCancelled) {
- return state;
- }
-
- return {
- ...state,
- error: action.error,
- loading: false,
- wasLoaded: true,
- };
- }
- case SET_DATA_WAS_NOT_LOADED: {
- return {
- ...state,
- wasLoaded: false,
- };
- }
- default:
- return state;
- }
-};
-
-export const getTopStorageGroups = ({
- tenant,
- visibleEntities = 'all',
- nodeId,
- sortOrder = -1,
- sortValue = 'Usage',
- limit = TENANT_OVERVIEW_TABLES_LIMIT,
- version = EVersion.v2,
- ...params
-}: StorageApiRequestParams) => {
- return createApiRequest({
- request: window.api.getStorageInfo(
- {tenant, visibleEntities, nodeId, version, sortOrder, sortValue, limit, ...params},
- {concurrentId: 'getTopStorageGroups'},
- ),
- actions: FETCH_TOP_STORAGE_GROUPS,
- dataHandler: prepareTopStorageGroupsResponse,
- });
-};
-
-export const selectTopStorageGroups = (state: TopStorageGroupsStateSlice) =>
- state.topStorageGroups.data;
-
-export const setDataWasNotLoaded = () => {
- return {
- type: SET_DATA_WAS_NOT_LOADED,
- } as const;
-};
-
-export default topStorageGroups;
+export const topStorageGroupsApi = api.injectEndpoints({
+ endpoints: (builder) => ({
+ getTopStorageGroups: builder.query({
+ queryFn: async (params: StorageApiRequestParams, {signal}) => {
+ try {
+ const data = await window.api.getStorageInfo(
+ {
+ visibleEntities: 'all',
+ sortOrder: -1,
+ sortValue: 'Usage',
+ limit: TENANT_OVERVIEW_TABLES_LIMIT,
+ version: EVersion.v2,
+ ...params,
+ },
+ {signal},
+ );
+ return {data: prepareTopStorageGroupsResponse(data).groups || []};
+ } catch (error) {
+ return {error};
+ }
+ },
+ providesTags: ['All'],
+ }),
+ }),
+});
diff --git a/src/store/reducers/tenantOverview/topStorageGroups/types.ts b/src/store/reducers/tenantOverview/topStorageGroups/types.ts
index 90cb763d8..69ce6c7f8 100644
--- a/src/store/reducers/tenantOverview/topStorageGroups/types.ts
+++ b/src/store/reducers/tenantOverview/topStorageGroups/types.ts
@@ -1,30 +1,5 @@
-import type {IResponseError} from '../../../../types/api/error';
-import type {ApiRequestAction} from '../../../utils';
import type {PreparedStorageGroup} from '../../storage/types';
-import type {FETCH_TOP_STORAGE_GROUPS, setDataWasNotLoaded} from './topStorageGroups';
-
-export interface TopStorageGroupsState {
- loading: boolean;
- wasLoaded: boolean;
- data?: PreparedStorageGroup[];
- error?: IResponseError;
-}
-
export interface PreparedTopStorageGroupsResponse {
groups?: PreparedStorageGroup[];
}
-
-type GetTopStorageGroupApiRequestAction = ApiRequestAction<
- typeof FETCH_TOP_STORAGE_GROUPS,
- PreparedTopStorageGroupsResponse,
- IResponseError
->;
-
-export type TopStorageGroupsAction =
- | GetTopStorageGroupApiRequestAction
- | ReturnType;
-
-export interface TopStorageGroupsStateSlice {
- topStorageGroups: TopStorageGroupsState;
-}