Skip to content

Commit 479a991

Browse files
[ML] DF Analytics: allow failed job to be stopped by force via the UI (#74710)
* allow force stop from ui if job is failed * update wording in confirm modal
1 parent ad3d875 commit 479a991

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_stop/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
*/
66

77
export { StopButton } from './stop_button';
8+
export { StopButtonModal } from './stop_button_modal';
9+
export { useForceStopAction } from './use_force_stop_action';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React, { FC } from 'react';
8+
import { i18n } from '@kbn/i18n';
9+
import { FormattedMessage } from '@kbn/i18n/react';
10+
import { EuiConfirmModal, EuiOverlayMask, EUI_MODAL_CONFIRM_BUTTON } from '@elastic/eui';
11+
12+
import { ForceStopAction } from './use_force_stop_action';
13+
14+
export const StopButtonModal: FC<ForceStopAction> = ({
15+
closeModal,
16+
item,
17+
forceStopAndCloseModal,
18+
}) => {
19+
return (
20+
<>
21+
{item !== undefined && (
22+
<EuiOverlayMask>
23+
<EuiConfirmModal
24+
title={i18n.translate('xpack.ml.dataframe.analyticsList.forceStopModalTitle', {
25+
defaultMessage: 'Force this job to stop?',
26+
})}
27+
onCancel={closeModal}
28+
onConfirm={forceStopAndCloseModal}
29+
cancelButtonText={i18n.translate(
30+
'xpack.ml.dataframe.analyticsList.forceStopModalCancelButton',
31+
{
32+
defaultMessage: 'Cancel',
33+
}
34+
)}
35+
confirmButtonText={i18n.translate(
36+
'xpack.ml.dataframe.analyticsList.forceStopModalStartButton',
37+
{
38+
defaultMessage: 'Force stop',
39+
}
40+
)}
41+
defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON}
42+
buttonColor="primary"
43+
>
44+
<p>
45+
<FormattedMessage
46+
id="xpack.ml.dataframe.analyticsList.forceStopModalBody"
47+
defaultMessage="{analyticsId} is in a failed state. You must stop the job and fix the failure."
48+
values={{ analyticsId: item.config.id }}
49+
/>
50+
</p>
51+
</EuiConfirmModal>
52+
</EuiOverlayMask>
53+
)}
54+
</>
55+
);
56+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { useState } from 'react';
8+
9+
import { DataFrameAnalyticsListRow } from '../analytics_list/common';
10+
import { stopAnalytics } from '../../services/analytics_service';
11+
12+
export type ForceStopAction = ReturnType<typeof useForceStopAction>;
13+
export const useForceStopAction = () => {
14+
const [isModalVisible, setModalVisible] = useState(false);
15+
16+
const [item, setItem] = useState<DataFrameAnalyticsListRow>();
17+
18+
const closeModal = () => setModalVisible(false);
19+
const forceStopAndCloseModal = () => {
20+
if (item !== undefined) {
21+
setModalVisible(false);
22+
stopAnalytics(item);
23+
}
24+
};
25+
26+
const openModal = (newItem: DataFrameAnalyticsListRow) => {
27+
setItem(newItem);
28+
setModalVisible(true);
29+
};
30+
31+
return {
32+
closeModal,
33+
isModalVisible,
34+
item,
35+
openModal,
36+
forceStopAndCloseModal,
37+
};
38+
};

x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/use_actions.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import {
2121
EditButtonFlyout,
2222
} from '../action_edit';
2323
import { useStartAction, StartButton, StartButtonModal } from '../action_start';
24-
import { StopButton } from '../action_stop';
24+
import { StopButton, useForceStopAction, StopButtonModal } from '../action_stop';
2525
import { getViewAction } from '../action_view';
2626

2727
import {
2828
isCompletedAnalyticsJob,
2929
isDataFrameAnalyticsRunning,
30+
isDataFrameAnalyticsFailed,
3031
DataFrameAnalyticsListRow,
3132
} from './common';
3233

@@ -53,11 +54,13 @@ export const useActions = (
5354
const deleteAction = useDeleteAction();
5455
const editAction = useEditAction();
5556
const startAction = useStartAction();
57+
const stopAction = useForceStopAction();
5658
/* eslint-disable react-hooks/rules-of-hooks */
5759

5860
modals = (
5961
<>
6062
{startAction.isModalVisible && <StartButtonModal {...startAction} />}
63+
{stopAction.isModalVisible && <StopButtonModal {...stopAction} />}
6164
{deleteAction.isModalVisible && <DeleteButtonModal {...deleteAction} />}
6265
{isEditActionFlyoutVisible(editAction) && <EditButtonFlyout {...editAction} />}
6366
</>
@@ -78,7 +81,10 @@ export const useActions = (
7881
...[
7982
{
8083
render: (item: DataFrameAnalyticsListRow) => {
81-
if (!isDataFrameAnalyticsRunning(item.stats.state)) {
84+
if (
85+
!isDataFrameAnalyticsRunning(item.stats.state) &&
86+
!isDataFrameAnalyticsFailed(item.stats.state)
87+
) {
8288
return (
8389
<StartButton
8490
canStartStopDataFrameAnalytics={canStartStopDataFrameAnalytics}
@@ -99,7 +105,11 @@ export const useActions = (
99105
item={item}
100106
onClick={() => {
101107
if (canStartStopDataFrameAnalytics) {
102-
stopAnalytics(item);
108+
if (isDataFrameAnalyticsFailed(item.stats.state)) {
109+
stopAction.openModal(item);
110+
} else {
111+
stopAnalytics(item);
112+
}
103113
}
104114
}}
105115
/>

0 commit comments

Comments
 (0)