Skip to content

Commit ec8d8d2

Browse files
committed
[ML] Lazy ml node UI improvements
1 parent b058f78 commit ec8d8d2

File tree

8 files changed

+50
-12
lines changed

8 files changed

+50
-12
lines changed

x-pack/plugins/ml/common/types/modules.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export interface KibanaObjectResponse extends ResultItem {
6868

6969
export interface DatafeedResponse extends ResultItem {
7070
started: boolean;
71+
awaitingMlNodeAllocation?: boolean;
7172
error?: ErrorType;
7273
}
7374

x-pack/plugins/ml/public/application/components/jobs_awaiting_node_warning/jobs_awaiting_node_warning.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import React, { Fragment, FC } from 'react';
99

1010
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
1111
import { FormattedMessage } from '@kbn/i18n/react';
12-
import { isCloud } from '../../services/ml_server_info';
12+
import { lazyMlNodesAvailable } from '../../ml_nodes_check';
1313

1414
interface Props {
1515
jobCount: number;
1616
}
1717

1818
export const JobsAwaitingNodeWarning: FC<Props> = ({ jobCount }) => {
19-
if (isCloud() === false || jobCount === 0) {
19+
if (lazyMlNodesAvailable() === false || jobCount === 0) {
2020
return null;
2121
}
2222

@@ -26,7 +26,7 @@ export const JobsAwaitingNodeWarning: FC<Props> = ({ jobCount }) => {
2626
title={
2727
<FormattedMessage
2828
id="xpack.ml.jobsAwaitingNodeWarning.title"
29-
defaultMessage="Awaiting ML node provisioning"
29+
defaultMessage="Awaiting machine learning node"
3030
/>
3131
}
3232
color="primary"

x-pack/plugins/ml/public/application/components/jobs_awaiting_node_warning/new_job_awaiting_node.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@ import React, { Fragment, FC } from 'react';
1010
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
1111
import { FormattedMessage } from '@kbn/i18n/react';
1212
import { JobType } from '../../../../common/types/saved_objects';
13+
import { lazyMlNodesAvailable } from '../../ml_nodes_check';
1314

1415
interface Props {
1516
jobType: JobType;
1617
}
1718

1819
export const NewJobAwaitingNodeWarning: FC<Props> = () => {
20+
if (lazyMlNodesAvailable() === false) {
21+
return null;
22+
}
23+
1924
return (
2025
<Fragment>
2126
<EuiCallOut
2227
title={
2328
<FormattedMessage
2429
id="xpack.ml.jobsAwaitingNodeWarning.title"
25-
defaultMessage="Awaiting ML node provisioning"
30+
defaultMessage="Awaiting machine learning node"
2631
/>
2732
}
2833
color="primary"
@@ -31,7 +36,7 @@ export const NewJobAwaitingNodeWarning: FC<Props> = () => {
3136
<div>
3237
<FormattedMessage
3338
id="xpack.ml.newJobAwaitingNodeWarning.noMLNodesAvailableDescription"
34-
defaultMessage="Job cannot be started straight away, an ML node needs to be started. This will happen automatically."
39+
defaultMessage="There are currently no nodes that can run the job, therefore it will remain in OPENING state until an appropriate node becomes available."
3540
/>
3641
</div>
3742
</EuiCallOut>

x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { TimeRange } from '../common/components';
4343
import { JobId } from '../../../../../common/types/anomaly_detection_jobs';
4444
import { ML_PAGES } from '../../../../../common/constants/ml_url_generator';
4545
import { TIME_FORMAT } from '../../../../../common/constants/time_format';
46+
import { JobsAwaitingNodeWarning } from '../../../components/jobs_awaiting_node_warning';
4647

4748
export interface ModuleJobUI extends ModuleJob {
4849
datafeedResult?: DatafeedResponse;
@@ -84,6 +85,7 @@ export const Page: FC<PageProps> = ({ moduleId, existingGroupIds }) => {
8485
const [saveState, setSaveState] = useState<SAVE_STATE>(SAVE_STATE.NOT_SAVED);
8586
const [resultsUrl, setResultsUrl] = useState<string>('');
8687
const [existingGroups, setExistingGroups] = useState(existingGroupIds);
88+
const [jobsAwaitingNodeCount, setJobsAwaitingNodeCount] = useState(0);
8789
// #endregion
8890

8991
const {
@@ -204,9 +206,19 @@ export const Page: FC<PageProps> = ({ moduleId, existingGroupIds }) => {
204206
});
205207

206208
setResultsUrl(url);
207-
const failedJobsCount = jobsResponse.reduce((count, { success }) => {
208-
return success ? count : count + 1;
209-
}, 0);
209+
const failedJobsCount = jobsResponse.reduce(
210+
(count, { success }) => (success ? count : count + 1),
211+
0
212+
);
213+
214+
const lazyJobsCount = datafeedsResponse.reduce(
215+
(count, { awaitingMlNodeAllocation }) =>
216+
awaitingMlNodeAllocation === true ? count + 1 : count,
217+
0
218+
);
219+
220+
setJobsAwaitingNodeCount(lazyJobsCount);
221+
210222
setSaveState(
211223
failedJobsCount === 0
212224
? SAVE_STATE.SAVED
@@ -291,6 +303,8 @@ export const Page: FC<PageProps> = ({ moduleId, existingGroupIds }) => {
291303
</>
292304
)}
293305

306+
{jobsAwaitingNodeCount > 0 && <JobsAwaitingNodeWarning jobCount={jobsAwaitingNodeCount} />}
307+
294308
<EuiFlexGroup wrap={true} gutterSize="m">
295309
<EuiFlexItem grow={1}>
296310
<EuiPanel grow={false}>

x-pack/plugins/ml/public/application/ml_nodes_check/check_ml_nodes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export function mlNodesAvailable() {
4848
return mlNodeCount !== 0 || lazyMlNodeCount !== 0;
4949
}
5050

51+
export function currentMlNodesAvailable() {
52+
return mlNodeCount !== 0;
53+
}
54+
55+
export function lazyMlNodesAvailable() {
56+
return lazyMlNodeCount !== 0;
57+
}
58+
5159
export function permissionToViewMlNodeCount() {
5260
return userHasPermissionToViewMlNodeCount;
5361
}

x-pack/plugins/ml/public/application/ml_nodes_check/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export {
99
checkMlNodesAvailable,
1010
getMlNodeCount,
1111
mlNodesAvailable,
12+
lazyMlNodesAvailable,
1213
permissionToViewMlNodeCount,
1314
} from './check_ml_nodes';

x-pack/plugins/ml/public/application/timeseriesexplorer/components/forecasting_modal/run_controls.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
import { JOB_STATE } from '../../../../../common/constants/states';
2828
import { FORECAST_DURATION_MAX_DAYS } from './forecasting_modal';
2929
import { ForecastProgress } from './forecast_progress';
30-
import { mlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes';
30+
import { currentMlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes';
3131
import {
3232
checkPermission,
3333
createPermissionFailureMessage,
@@ -41,7 +41,7 @@ function getRunInputDisabledState(job, isForecastRequested) {
4141
// - No canForecastJob permission
4242
// - Job is not in an OPENED or CLOSED state
4343
// - A new forecast has been requested
44-
if (mlNodesAvailable() === false) {
44+
if (currentMlNodesAvailable() === false) {
4545
return {
4646
isDisabled: true,
4747
isDisabledToolTipText: i18n.translate(

x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ export class DataRecognizer {
491491
const startedDatafeed = startResults[df.id];
492492
if (startedDatafeed !== undefined) {
493493
df.started = startedDatafeed.started;
494+
df.awaitingMlNodeAllocation = startedDatafeed.awaitingMlNodeAllocation;
494495
if (startedDatafeed.error !== undefined) {
495496
df.error = startedDatafeed.error;
496497
}
@@ -811,11 +812,18 @@ export class DataRecognizer {
811812
duration.end = (end as unknown) as string;
812813
}
813814

814-
await this._mlClient.startDatafeed({
815+
const {
816+
body: { started, node },
817+
} = await this._mlClient.startDatafeed<{
818+
started: boolean;
819+
node: string;
820+
}>({
815821
datafeed_id: datafeed.id,
816822
...duration,
817823
});
818-
result.started = true;
824+
825+
result.started = started;
826+
result.awaitingMlNodeAllocation = node?.length === 0;
819827
} catch ({ body }) {
820828
result.started = false;
821829
result.error = body;
@@ -845,6 +853,7 @@ export class DataRecognizer {
845853
if (d.id === d2.id) {
846854
d.success = d2.success;
847855
d.started = d2.started;
856+
d.awaitingMlNodeAllocation = d2.awaitingMlNodeAllocation;
848857
if (d2.error !== undefined) {
849858
d.error = d2.error;
850859
}

0 commit comments

Comments
 (0)