Skip to content

Commit

Permalink
feat: stop running query
Browse files Browse the repository at this point in the history
  • Loading branch information
astandrik committed Aug 5, 2024
1 parent 3e463ed commit 39d2575
Show file tree
Hide file tree
Showing 17 changed files with 407 additions and 215 deletions.
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
"@gravity-ui/navigation": "^2.16.0",
"@gravity-ui/paranoid": "^2.0.1",
"@gravity-ui/react-data-table": "^2.1.1",
"@gravity-ui/table": "^0.5.0",
"@gravity-ui/uikit": "^6.20.1",
"@gravity-ui/websql-autocomplete": "^9.1.0",
"@reduxjs/toolkit": "^2.2.3",
"@tanstack/react-table": "^8.19.3",
"axios": "^1.7.2",
"axios-retry": "^4.4.0",
"colord": "^2.9.3",
Expand All @@ -50,11 +52,10 @@
"tslib": "^2.6.3",
"url": "^0.11.3",
"use-query-params": "^2.2.1",
"uuid": "^10.0.0",
"web-vitals": "^1.1.2",
"ydb-ui-components": "^4.2.0",
"zod": "^3.23.8",
"@gravity-ui/table": "^0.5.0",
"@tanstack/react-table": "^8.19.3"
"zod": "^3.23.8"
},
"scripts": {
"analyze": "source-map-explorer 'build/static/js/*.js'",
Expand Down Expand Up @@ -144,6 +145,7 @@
"@types/react-dom": "^18.3.0",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"@types/uuid": "^10.0.0",
"copyfiles": "^2.4.1",
"http-proxy-middleware": "^2.0.6",
"husky": "^9.0.11",
Expand Down
10 changes: 7 additions & 3 deletions src/components/QueryExecutionStatus/QueryExecutionStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

import {CircleCheck, CircleInfo, CircleQuestionFill, CircleXmark} from '@gravity-ui/icons';
import {Icon, Tooltip} from '@gravity-ui/uikit';
import {Icon, Spin, Tooltip} from '@gravity-ui/uikit';
import {isAxiosError} from 'axios';

import i18n from '../../containers/Tenant/Query/i18n';
Expand All @@ -16,6 +16,7 @@ const b = cn('kv-query-execution-status');
interface QueryExecutionStatusProps {
className?: string;
error?: unknown;
loading?: boolean;
}

const QuerySettingsIndicator = () => {
Expand All @@ -40,11 +41,14 @@ const QuerySettingsIndicator = () => {
);
};

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

if (isAxiosError(error) && error.code === 'ECONNABORTED') {
if (loading) {
icon = <Spin size="xs" />;
label = 'Running';
} else if (isAxiosError(error) && error.code === 'ECONNABORTED') {
icon = <Icon data={CircleQuestionFill} />;
label = 'Connection aborted';
} else {
Expand Down
26 changes: 0 additions & 26 deletions src/containers/Tenant/Query/ExecuteResult/ExecuteResult.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,6 @@
padding: 15px 10px;
}

&__controls {
position: sticky;
z-index: 2;
top: 0;

display: flex;
justify-content: space-between;
align-items: center;

height: 53px;
padding: 12px 20px;

border-bottom: 1px solid var(--g-color-line-generic);
background-color: var(--g-color-base-background);
}

&__controls-right {
display: flex;
gap: 12px;

height: 100%;
}
&__controls-left {
display: flex;
gap: 4px;
}
&__inspector {
overflow: auto;

Expand Down
84 changes: 32 additions & 52 deletions src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import React from 'react';

import type {ControlGroupOption} from '@gravity-ui/uikit';
import {RadioButton, Tabs} from '@gravity-ui/uikit';
import {Tabs} from '@gravity-ui/uikit';
import JSONTree from 'react-json-inspector';

import {ClipboardButton} from '../../../../components/ClipboardButton';
import Divider from '../../../../components/Divider/Divider';
import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton';
import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
import {YDBGraph} from '../../../../components/Graph/Graph';
import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
import {LoaderWrapper} from '../../../../components/LoaderWrapper/LoaderWrapper';
import {QueryResultTable} from '../../../../components/QueryResultTable/QueryResultTable';
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
import type {ColumnType, KeyValueRow, TKqpStatsQuery} from '../../../../types/api/query';
import type {ValueOf} from '../../../../types/common';
import type {IQueryResult} from '../../../../types/store/query';
import {getArray} from '../../../../utils';
import {cn} from '../../../../utils/cn';
import {useTypedDispatch} from '../../../../utils/hooks';
import {parseQueryError} from '../../../../utils/query';
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
import {SimplifiedPlan} from '../ExplainResult/components/SimplifiedPlan/SimplifiedPlan';
import {ResultIssues} from '../Issues/Issues';
import {QueryDuration} from '../QueryDuration/QueryDuration';
import {QuerySettingsBanner} from '../QuerySettingsBanner/QuerySettingsBanner';
import {ResultControls} from '../ResultControls/ResultControls';
import {getPreparedResult} from '../utils/getPreparedResult';

import i18n from './i18n';
Expand All @@ -48,7 +44,9 @@ interface ExecuteResultProps {
isResultsCollapsed?: boolean;
onCollapseResults: VoidFunction;
onExpandResults: VoidFunction;
onStopButtonClick: VoidFunction;
theme?: string;
loading?: boolean;
}

export function ExecuteResult({
Expand All @@ -57,13 +55,15 @@ export function ExecuteResult({
isResultsCollapsed,
onCollapseResults,
onExpandResults,
onStopButtonClick,
theme,
loading,
}: ExecuteResultProps) {
const [selectedResultSet, setSelectedResultSet] = React.useState(0);
const [activeSection, setActiveSection] = React.useState<SectionID>(resultOptionsIds.result);
const dispatch = useTypedDispatch();

const stats = data?.stats;
const stats: TKqpStatsQuery | undefined = data?.stats;
const resultsSetsCount = data?.resultSets?.length;
const isMulti = resultsSetsCount && resultsSetsCount > 0;
const currentResult = isMulti ? data?.resultSets?.[selectedResultSet].result : data?.result;
Expand All @@ -72,15 +72,15 @@ export function ExecuteResult({
const copyDisabled = !textResults.length;
const {plan, simplifiedPlan} = React.useMemo(() => getPlan(data), [data]);

const resultOptions: ControlGroupOption<SectionID>[] = [
const executeOptions: ControlGroupOption<SectionID>[] = [
{value: resultOptionsIds.result, content: i18n('action.result')},
{value: resultOptionsIds.stats, content: i18n('action.stats')},
];
if (plan) {
resultOptions.push({value: resultOptionsIds.schema, content: i18n('action.schema')});
executeOptions.push({value: resultOptionsIds.schema, content: i18n('action.schema')});
}
if (simplifiedPlan) {
resultOptions.push({
executeOptions.push({
value: resultOptionsIds.simplified,
content: i18n('action.explain-plan'),
});
Expand All @@ -94,8 +94,8 @@ export function ExecuteResult({
};
}, [dispatch]);

const onSelectSection = (value: string) => {
setActiveSection(value as SectionID);
const onSelectSection = (value: SectionID) => {
setActiveSection(value);
};

const renderResultTable = (
Expand Down Expand Up @@ -129,17 +129,6 @@ export function ExecuteResult({
);
};

const renderClipboardButton = () => {
return (
<ClipboardButton
text={textResults}
view="flat-secondary"
title="Copy results"
disabled={copyDisabled}
/>
);
};

const renderStats = () => {
return (
<div className={b('inspector')}>
Expand Down Expand Up @@ -209,34 +198,25 @@ export function ExecuteResult({

return (
<React.Fragment>
<div className={b('controls')}>
<div className={b('controls-right')}>
<QueryExecutionStatus error={error} />
{stats && !error && (
<React.Fragment>
<QueryDuration duration={stats?.DurationUs} />
<Divider />
<RadioButton
options={resultOptions}
value={activeSection}
onUpdate={onSelectSection}
/>
</React.Fragment>
)}
</div>
<div className={b('controls-left')}>
{renderClipboardButton()}
<EnableFullscreenButton />
<PaneVisibilityToggleButtons
onCollapse={onCollapseResults}
onExpand={onExpandResults}
isCollapsed={isResultsCollapsed}
initialDirection="bottom"
/>
</div>
</div>
<ResultControls<SectionID>
error={error}
stats={stats ? {DurationUs: stats.DurationUs} : undefined}
activeSection={activeSection}
onSelectSection={onSelectSection}
sectionOptions={executeOptions}
clipboardText={textResults}
isClipboardDisabled={copyDisabled}
isResultsCollapsed={isResultsCollapsed}
onCollapseResults={onCollapseResults}
onExpandResults={onExpandResults}
onStopButtonClick={onStopButtonClick}
isFullscreenDisabled={Boolean(error)}
loading={loading}
/>
<QuerySettingsBanner />
<Fullscreen>{renderResultSection()}</Fullscreen>
<LoaderWrapper loading={loading}>
<Fullscreen>{renderResultSection()}</Fullscreen>
</LoaderWrapper>
</React.Fragment>
);
}
34 changes: 0 additions & 34 deletions src/containers/Tenant/Query/ExplainResult/ExplainResult.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,4 @@
&__text-message {
padding: 15px 20px;
}

&__controls {
position: sticky;
z-index: 2;
top: 0;

display: flex;
justify-content: space-between;
align-items: center;

height: 53px;
padding: 12px 20px;

border-bottom: 1px solid var(--g-color-line-generic);
background-color: var(--g-color-base-background);
}
&__controls-right {
display: flex;
gap: 12px;

height: 100%;
}
&__controls-left {
display: flex;
gap: 4px;
}
&__loader {
display: flex;
justify-content: center;
align-items: center;

width: 100%;
margin-top: 20px;
}
}
Loading

0 comments on commit 39d2575

Please sign in to comment.