Variables: enables cancel for slow query variables queries (#24430)

* Refactor: initial commit

* Tests: updates tests

* Tests: updates snapshots

* Chore: updates after PR comments

* Chore: renamed initVariablesBatch

* Tests: adds transactionReducer tests

* Chore: updates after PR comments

* Refactor: renames cancelAllDataSourceRequests

* Refactor: reduces cancellation complexity

* Tests: adds tests for cancelAllInFlightRequests

* Tests: adds initVariablesTransaction tests

* Tests: adds tests for cleanUpVariables and cancelVariables

* Always cleanup dashboard on unmount, even if init is in progress. Check if init phase has changed after services init is completed

* fixed failing tests and added some more to test new scenario.

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
This commit is contained in:
Hugo Häggmark
2020-06-04 08:59:57 +02:00
committed by GitHub
parent 0f5b894256
commit e65dbcfea1
19 changed files with 561 additions and 90 deletions

View File

@@ -2,19 +2,15 @@ import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { DashboardPage, mapStateToProps, Props, State } from './DashboardPage';
import { DashboardModel } from '../state';
import { cleanUpDashboard } from '../state/reducers';
import {
mockToolkitActionCreator,
mockToolkitActionCreatorWithoutPayload,
ToolkitActionCreatorWithoutPayloadMockType,
} from 'test/core/redux/mocks';
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
import { DashboardInitPhase, DashboardRouteInfo } from 'app/types';
import { notifyApp, updateLocation } from 'app/core/actions';
import { cleanUpDashboardAndVariables } from '../state/actions';
jest.mock('app/features/dashboard/components/DashboardSettings/SettingsCtrl', () => ({}));
interface ScenarioContext {
cleanUpDashboardMock: ToolkitActionCreatorWithoutPayloadMockType;
cleanUpDashboardAndVariablesMock: typeof cleanUpDashboardAndVariables;
dashboard?: DashboardModel | null;
setDashboardProp: (overrides?: any, metaOverrides?: any) => void;
wrapper?: ShallowWrapper<Props, State, DashboardPage>;
@@ -47,7 +43,7 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
let setupFn: () => void;
const ctx: ScenarioContext = {
cleanUpDashboardMock: mockToolkitActionCreatorWithoutPayload(cleanUpDashboard),
cleanUpDashboardAndVariablesMock: jest.fn(),
setup: fn => {
setupFn = fn;
},
@@ -67,7 +63,8 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
initDashboard: jest.fn(),
updateLocation: mockToolkitActionCreator(updateLocation),
notifyApp: mockToolkitActionCreator(notifyApp),
cleanUpDashboard: ctx.cleanUpDashboardMock,
cleanUpDashboardAndVariables: ctx.cleanUpDashboardAndVariablesMock,
cancelVariables: jest.fn(),
dashboard: null,
};
@@ -233,7 +230,7 @@ describe('DashboardPage', () => {
});
it('Should call clean up action', () => {
expect(ctx.cleanUpDashboardMock).toHaveBeenCalledTimes(1);
expect(ctx.cleanUpDashboardAndVariablesMock).toHaveBeenCalledTimes(1);
});
});

View File

@@ -8,16 +8,14 @@ import classNames from 'classnames';
import { createErrorNotification } from 'app/core/copy/appNotification';
import { getMessageFromError } from 'app/core/utils/errors';
import { Branding } from 'app/core/components/Branding/Branding';
// Components
import { DashboardGrid } from '../dashgrid/DashboardGrid';
import { DashNav } from '../components/DashNav';
import { DashboardSettings } from '../components/DashboardSettings';
import { PanelEditor } from '../components/PanelEditor/PanelEditor';
import { Alert, CustomScrollbar, Icon } from '@grafana/ui';
import { Alert, Button, CustomScrollbar, HorizontalGroup, Icon, VerticalGroup } from '@grafana/ui';
// Redux
import { initDashboard } from '../state/initDashboard';
import { cleanUpDashboard } from '../state/reducers';
import { notifyApp, updateLocation } from 'app/core/actions';
// Types
import {
@@ -32,6 +30,8 @@ import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { InspectTab, PanelInspector } from '../components/Inspector/PanelInspector';
import { getConfig } from '../../../core/config';
import { SubMenu } from '../components/SubMenu/SubMenu';
import { cleanUpDashboardAndVariables } from '../state/actions';
import { cancelVariables } from '../../variables/state/actions';
export interface Props {
urlUid?: string;
@@ -51,11 +51,12 @@ export interface Props {
dashboard: DashboardModel | null;
initError?: DashboardInitError;
initDashboard: typeof initDashboard;
cleanUpDashboard: typeof cleanUpDashboard;
cleanUpDashboardAndVariables: typeof cleanUpDashboardAndVariables;
notifyApp: typeof notifyApp;
updateLocation: typeof updateLocation;
inspectTab?: InspectTab;
isPanelEditorOpen?: boolean;
cancelVariables: typeof cancelVariables;
}
export interface State {
@@ -90,10 +91,8 @@ export class DashboardPage extends PureComponent<Props, State> {
}
componentWillUnmount() {
if (this.props.dashboard) {
this.props.cleanUpDashboard();
this.setPanelFullscreenClass(false);
}
this.props.cleanUpDashboardAndVariables();
this.setPanelFullscreenClass(false);
}
componentDidUpdate(prevProps: Props) {
@@ -210,11 +209,24 @@ export class DashboardPage extends PureComponent<Props, State> {
this.setState({ updateScrollTop: 0 });
};
cancelVariables = () => {
this.props.updateLocation({ path: '/' });
};
renderSlowInitState() {
return (
<div className="dashboard-loading">
<div className="dashboard-loading__text">
<Icon name="fa fa-spinner" className="fa-spin" /> {this.props.initPhase}
<VerticalGroup spacing="md">
<HorizontalGroup align="center" justify="center" spacing="xs">
<Icon name="fa fa-spinner" className="fa-spin" /> {this.props.initPhase}
</HorizontalGroup>{' '}
<HorizontalGroup align="center" justify="center">
<Button variant="secondary" size="md" icon="repeat" onClick={this.cancelVariables}>
Cancel loading dashboard
</Button>
</HorizontalGroup>
</VerticalGroup>
</div>
</div>
);
@@ -336,9 +348,10 @@ export const mapStateToProps = (state: StoreState) => ({
const mapDispatchToProps = {
initDashboard,
cleanUpDashboard,
cleanUpDashboardAndVariables,
notifyApp,
updateLocation,
cancelVariables,
};
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DashboardPage));

View File

@@ -320,12 +320,36 @@ exports[`DashboardPage Dashboard is fetching slowly Should render slow init stat
<div
className="dashboard-loading__text"
>
<Icon
className="fa-spin"
name="fa fa-spinner"
/>
Fetching
<Component
spacing="md"
>
<Component
align="center"
justify="center"
spacing="xs"
>
<Icon
className="fa-spin"
name="fa fa-spinner"
/>
Fetching
</Component>
<Component
align="center"
justify="center"
>
<Button
icon="repeat"
onClick={[Function]}
size="md"
variant="secondary"
>
Cancel loading dashboard
</Button>
</Component>
</Component>
</div>
</div>
`;