Skip to content

Commit c4cd541

Browse files
fix(Query): parse 200 error response (#883)
1 parent bb8cdce commit c4cd541

File tree

32 files changed

+365
-398
lines changed

32 files changed

+365
-398
lines changed

src/components/Errors/ResponseError/ResponseError.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export const ResponseError = ({
1212
defaultMessage = i18n('responseError.defaultMessage'),
1313
}: ResponseErrorProps) => {
1414
let statusText = '';
15+
16+
if (error && typeof error === 'string') {
17+
statusText = error;
18+
}
1519
if (error && typeof error === 'object') {
1620
if ('statusText' in error && typeof error.statusText === 'string') {
1721
statusText = error.statusText;

src/components/QueryExecutionStatus/QueryExecutionStatus.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {CircleCheck, CircleQuestionFill, CircleXmark} from '@gravity-ui/icons';
22
import {Icon} from '@gravity-ui/uikit';
3-
import type {AxiosError} from 'axios';
3+
import {isAxiosError} from 'axios';
44

55
import {cn} from '../../utils/cn';
66

@@ -10,15 +10,14 @@ const b = cn('kv-query-execution-status');
1010

1111
interface QueryExecutionStatusProps {
1212
className?: string;
13-
// TODO: Remove Record<string, any> when ECONNABORTED error case is fully typed
14-
error?: AxiosError | Record<string, any> | string;
13+
error?: unknown;
1514
}
1615

1716
export const QueryExecutionStatus = ({className, error}: QueryExecutionStatusProps) => {
1817
let icon: React.ReactNode;
1918
let label: string;
2019

21-
if (typeof error === 'object' && error?.code === 'ECONNABORTED') {
20+
if (isAxiosError(error) && error.code === 'ECONNABORTED') {
2221
icon = <Icon data={CircleQuestionFill} />;
2322
label = 'Connection aborted';
2423
} else {

src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '../../../../../store/reducers/tenant/constants';
1313
import {topQueriesApi} from '../../../../../store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries';
1414
import {useTypedDispatch, useTypedSelector} from '../../../../../utils/hooks';
15+
import {parseQueryErrorToString} from '../../../../../utils/query';
1516
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
1617
import {
1718
TOP_QUERIES_COLUMNS_WIDTH_LS_KEY,
@@ -80,7 +81,7 @@ export function TopQueries({path}: TopQueriesProps) {
8081
onRowClick={handleRowClick}
8182
title={title}
8283
loading={loading}
83-
error={error}
84+
error={parseQueryErrorToString(error)}
8485
rowClassName={() => b('top-queries-row')}
8586
/>
8687
);

src/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {parseQuery} from '../../../../../routes';
44
import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../../../store/reducers/tenant/constants';
55
import {topShardsApi} from '../../../../../store/reducers/tenantOverview/topShards/tenantOverviewTopShards';
66
import {useTypedSelector} from '../../../../../utils/hooks';
7+
import {parseQueryErrorToString} from '../../../../../utils/query';
78
import {TenantTabsGroups, getTenantPath} from '../../../TenantPages';
89
import {
910
TOP_SHARDS_COLUMNS_WIDTH_LS_KEY,
@@ -50,7 +51,7 @@ export const TopShards = ({path}: TopShardsProps) => {
5051
columns={columns}
5152
title={title}
5253
loading={loading}
53-
error={error}
54+
error={parseQueryErrorToString(error)}
5455
/>
5556
);
5657
};

src/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {topTablesApi} from '../../../../../store/reducers/tenantOverview/execute
88
import type {KeyValueRow} from '../../../../../types/api/query';
99
import {formatBytes, getSizeWithSignificantDigits} from '../../../../../utils/bytesParsers';
1010
import {useTypedSelector} from '../../../../../utils/hooks';
11+
import {parseQueryErrorToString} from '../../../../../utils/query';
1112
import {TenantOverviewTableLayout} from '../TenantOverviewTableLayout';
1213
import {getSectionTitle} from '../getSectionTitle';
1314
import i18n from '../i18n';
@@ -73,7 +74,7 @@ export function TopTables({path}: TopTablesProps) {
7374
columns={columns}
7475
title={title}
7576
loading={loading}
76-
error={error}
77+
error={parseQueryErrorToString(error)}
7778
/>
7879
);
7980
}

src/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import type {EPathType} from '../../../../types/api/schema';
2222
import {cn} from '../../../../utils/cn';
2323
import {isSortableTopQueriesProperty} from '../../../../utils/diagnostics';
2424
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
25-
import {prepareQueryError} from '../../../../utils/query';
25+
import {parseQueryErrorToString} from '../../../../utils/query';
2626
import {TenantTabsGroups, getTenantPath} from '../../TenantPages';
2727
import {QUERY_TABLE_SETTINGS} from '../../utils/constants';
2828
import {isColumnEntityType} from '../../utils/schema';
@@ -91,8 +91,8 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
9191
};
9292

9393
const renderContent = () => {
94-
if (error && typeof error === 'object' && !(error as any).isCancelled) {
95-
return <div className="error">{prepareQueryError(error)}</div>;
94+
if (error) {
95+
return <div className="error">{parseQueryErrorToString(error)}</div>;
9696
}
9797

9898
if (!data || isColumnEntityType(type)) {

src/containers/Tenant/Diagnostics/TopShards/TopShards.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constan
1919
import {formatDateTime} from '../../../../utils/dataFormatters/dataFormatters';
2020
import {isSortableTopShardsProperty} from '../../../../utils/diagnostics';
2121
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
22-
import {prepareQueryError} from '../../../../utils/query';
22+
import {parseQueryErrorToString} from '../../../../utils/query';
2323
import {isColumnEntityType} from '../../utils/schema';
2424

2525
import {Filters} from './Filters';
@@ -192,8 +192,8 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
192192
};
193193

194194
const renderContent = () => {
195-
if (error && typeof error === 'object' && !(error as any).isCancelled) {
196-
return <div className="error">{prepareQueryError(error)}</div>;
195+
if (error) {
196+
return <div className="error">{parseQueryErrorToString(error)}</div>;
197197
}
198198

199199
if (!data || isColumnEntityType(type)) {

src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import {QueryResultTable} from '../../../../components/QueryResultTable/QueryRes
1212
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
1313
import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
1414
import type {ValueOf} from '../../../../types/common';
15-
import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
15+
import type {IQueryResult} from '../../../../types/store/query';
1616
import {getArray} from '../../../../utils';
1717
import {cn} from '../../../../utils/cn';
1818
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
19-
import {prepareQueryError} from '../../../../utils/query';
19+
import {parseQueryError} from '../../../../utils/query';
2020
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
2121
import {ResultIssues} from '../Issues/Issues';
2222
import {QueryDuration} from '../QueryDuration/QueryDuration';
@@ -41,7 +41,7 @@ const resultOptions = [
4141
interface ExecuteResultProps {
4242
data: IQueryResult | undefined;
4343
stats: IQueryResult['stats'] | undefined;
44-
error: string | QueryErrorResponse | undefined;
44+
error: unknown;
4545
isResultsCollapsed?: boolean;
4646
onCollapseResults: VoidFunction;
4747
onExpandResults: VoidFunction;
@@ -68,6 +68,8 @@ export function ExecuteResult({
6868
const textResults = getPreparedResult(currentResult);
6969
const copyDisabled = !textResults.length;
7070

71+
const parsedError = parseQueryError(error);
72+
7173
React.useEffect(() => {
7274
return () => {
7375
dispatch(disableFullscreen());
@@ -159,12 +161,12 @@ export function ExecuteResult({
159161
};
160162

161163
const renderIssues = () => {
162-
if (!error) {
164+
if (!parsedError) {
163165
return null;
164166
}
165167

166-
if (typeof error === 'object' && error.data?.issues && Array.isArray(error.data.issues)) {
167-
const content = <ResultIssues data={error.data} />;
168+
if (typeof parsedError === 'object') {
169+
const content = <ResultIssues data={parsedError} />;
168170

169171
return (
170172
<React.Fragment>
@@ -180,8 +182,6 @@ export function ExecuteResult({
180182
);
181183
}
182184

183-
const parsedError = typeof error === 'string' ? error : prepareQueryError(error);
184-
185185
return <div className={b('error')}>{parsedError}</div>;
186186
};
187187

src/containers/Tenant/Query/ExplainResult/ExplainResult.js

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import EnableFullscreenButton from '../../../../components/EnableFullscreenButto
99
import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
1010
import {MonacoEditor} from '../../../../components/MonacoEditor/MonacoEditor';
1111
import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
12-
import {explainVersions} from '../../../../store/reducers/explainQuery';
12+
import {explainVersions} from '../../../../store/reducers/explainQuery/utils';
1313
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
1414
import {cn} from '../../../../utils/cn';
1515
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
1616
import {LANGUAGE_S_EXPRESSION_ID} from '../../../../utils/monaco/s-expression/constants';
17+
import {parseQueryErrorToString} from '../../../../utils/query';
1718
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
1819

1920
import {renderExplainNode} from './utils';
@@ -193,22 +194,12 @@ export function ExplainResult(props) {
193194
};
194195

195196
const renderError = () => {
196-
const {error} = props;
197-
198-
let message;
199-
200-
if (error.data) {
201-
message = typeof error.data === 'string' ? error.data : error.data.error?.message;
202-
} else {
203-
message = error;
204-
}
205-
206-
return <div className={b('text-message')}>{message}</div>;
197+
return <div className={b('text-message')}>{parseQueryErrorToString(props.error)}</div>;
207198
};
208199

209200
const renderContent = () => {
210-
const {error, loading, loadingAst} = props;
211-
if (loading || loadingAst) {
201+
const {error, loading} = props;
202+
if (loading) {
212203
return renderLoader();
213204
}
214205

src/containers/Tenant/Query/Preview/Preview.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {setShowPreview} from '../../../../store/reducers/schema/schema';
99
import type {EPathType} from '../../../../types/api/schema';
1010
import {cn} from '../../../../utils/cn';
1111
import {useTypedDispatch, useTypedSelector} from '../../../../utils/hooks';
12-
import {prepareQueryError} from '../../../../utils/query';
12+
import {parseQueryErrorToString} from '../../../../utils/query';
1313
import {isExternalTableType, isTableType} from '../../utils/schema';
1414
import i18n from '../i18n';
1515

@@ -76,7 +76,9 @@ export const Preview = ({database, type}: PreviewProps) => {
7676
if (!isPreviewAvailable) {
7777
message = <div className={b('message-container')}>{i18n('preview.not-available')}</div>;
7878
} else if (error) {
79-
message = <div className={b('message-container', 'error')}>{prepareQueryError(error)}</div>;
79+
message = (
80+
<div className={b('message-container', 'error')}>{parseQueryErrorToString(error)}</div>
81+
);
8082
}
8183

8284
const content = message ?? (

0 commit comments

Comments
 (0)