[ML] DF Analytics: stop status polling when job stopped (#71159)

* clear interval if job stopped

* ensure analysisFieldsTable error messages up to date

* use shared constant for job state
This commit is contained in:
Melissa Alvarez 2020-07-09 20:37:32 -04:00 committed by GitHub
parent 1a81eb5c19
commit 87c8de8c7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 31 deletions

View file

@ -85,16 +85,27 @@ export const AnalysisFieldsTable: FC<{
includes: string[]; includes: string[];
loadingItems: boolean; loadingItems: boolean;
setFormState: React.Dispatch<React.SetStateAction<any>>; setFormState: React.Dispatch<React.SetStateAction<any>>;
minimumFieldsRequiredMessage?: string;
setMinimumFieldsRequiredMessage: React.Dispatch<React.SetStateAction<any>>;
tableItems: FieldSelectionItem[]; tableItems: FieldSelectionItem[];
}> = ({ dependentVariable, includes, loadingItems, setFormState, tableItems }) => { unsupportedFieldsError?: string;
setUnsupportedFieldsError: React.Dispatch<React.SetStateAction<any>>;
}> = ({
dependentVariable,
includes,
loadingItems,
setFormState,
minimumFieldsRequiredMessage,
setMinimumFieldsRequiredMessage,
tableItems,
unsupportedFieldsError,
setUnsupportedFieldsError,
}) => {
const [sortableProperties, setSortableProperties] = useState(); const [sortableProperties, setSortableProperties] = useState();
const [currentPaginationData, setCurrentPaginationData] = useState<{ const [currentPaginationData, setCurrentPaginationData] = useState<{
pageIndex: number; pageIndex: number;
itemsPerPage: number; itemsPerPage: number;
}>({ pageIndex: 0, itemsPerPage: 5 }); }>({ pageIndex: 0, itemsPerPage: 5 });
const [minimumFieldsRequiredMessage, setMinimumFieldsRequiredMessage] = useState<
undefined | string
>(undefined);
useEffect(() => { useEffect(() => {
if (includes.length === 0 && tableItems.length > 0) { if (includes.length === 0 && tableItems.length > 0) {
@ -164,8 +175,21 @@ export const AnalysisFieldsTable: FC<{
label={i18n.translate('xpack.ml.dataframe.analytics.create.includedFieldsLabel', { label={i18n.translate('xpack.ml.dataframe.analytics.create.includedFieldsLabel', {
defaultMessage: 'Included fields', defaultMessage: 'Included fields',
})} })}
isInvalid={minimumFieldsRequiredMessage !== undefined} fullWidth
error={minimumFieldsRequiredMessage} isInvalid={
minimumFieldsRequiredMessage !== undefined || unsupportedFieldsError !== undefined
}
error={[
...(minimumFieldsRequiredMessage !== undefined ? [minimumFieldsRequiredMessage] : []),
...(unsupportedFieldsError !== undefined
? [
i18n.translate('xpack.ml.dataframe.analytics.create.unsupportedFieldsError', {
defaultMessage: 'Invalid. {message}',
values: { message: unsupportedFieldsError },
}),
]
: []),
]}
> >
<Fragment /> <Fragment />
</EuiFormRow> </EuiFormRow>
@ -209,9 +233,10 @@ export const AnalysisFieldsTable: FC<{
) { ) {
selection = [dependentVariable]; selection = [dependentVariable];
} }
// If nothing selected show minimum fields required message and don't update form yet // If includes is empty show minimum fields required message and don't update form yet
if (selection.length === 0) { if (selection.length === 0) {
setMinimumFieldsRequiredMessage(minimumFieldsMessage); setMinimumFieldsRequiredMessage(minimumFieldsMessage);
setUnsupportedFieldsError(undefined);
} else { } else {
setMinimumFieldsRequiredMessage(undefined); setMinimumFieldsRequiredMessage(undefined);
setFormState({ includes: selection }); setFormState({ includes: selection });

View file

@ -73,6 +73,9 @@ export const ConfigurationStepForm: FC<CreateAnalyticsStepProps> = ({
const [includesTableItems, setIncludesTableItems] = useState<FieldSelectionItem[]>([]); const [includesTableItems, setIncludesTableItems] = useState<FieldSelectionItem[]>([]);
const [maxDistinctValuesError, setMaxDistinctValuesError] = useState<string | undefined>(); const [maxDistinctValuesError, setMaxDistinctValuesError] = useState<string | undefined>();
const [unsupportedFieldsError, setUnsupportedFieldsError] = useState<string | undefined>(); const [unsupportedFieldsError, setUnsupportedFieldsError] = useState<string | undefined>();
const [minimumFieldsRequiredMessage, setMinimumFieldsRequiredMessage] = useState<
undefined | string
>();
const { setEstimatedModelMemoryLimit, setFormState } = actions; const { setEstimatedModelMemoryLimit, setFormState } = actions;
const { estimatedModelMemoryLimit, form, isJobCreated, requestMessages } = state; const { estimatedModelMemoryLimit, form, isJobCreated, requestMessages } = state;
@ -117,6 +120,7 @@ export const ConfigurationStepForm: FC<CreateAnalyticsStepProps> = ({
dependentVariableEmpty || dependentVariableEmpty ||
jobType === undefined || jobType === undefined ||
maxDistinctValuesError !== undefined || maxDistinctValuesError !== undefined ||
minimumFieldsRequiredMessage !== undefined ||
requiredFieldsError !== undefined || requiredFieldsError !== undefined ||
unsupportedFieldsError !== undefined; unsupportedFieldsError !== undefined;
@ -400,32 +404,22 @@ export const ConfigurationStepForm: FC<CreateAnalyticsStepProps> = ({
)} )}
<EuiFormRow <EuiFormRow
fullWidth fullWidth
isInvalid={requiredFieldsError !== undefined || unsupportedFieldsError !== undefined} isInvalid={requiredFieldsError !== undefined}
error={[ error={i18n.translate('xpack.ml.dataframe.analytics.create.requiredFieldsError', {
...(requiredFieldsError !== undefined defaultMessage: 'Invalid. {message}',
? [ values: { message: requiredFieldsError },
i18n.translate('xpack.ml.dataframe.analytics.create.requiredFieldsError', { })}
defaultMessage: 'Invalid. {message}',
values: { message: requiredFieldsError },
}),
]
: []),
...(unsupportedFieldsError !== undefined
? [
i18n.translate('xpack.ml.dataframe.analytics.create.unsupportedFieldsError', {
defaultMessage: 'Invalid. {message}',
values: { message: unsupportedFieldsError },
}),
]
: []),
]}
> >
<Fragment /> <Fragment />
</EuiFormRow> </EuiFormRow>
<AnalysisFieldsTable <AnalysisFieldsTable
dependentVariable={dependentVariable} dependentVariable={dependentVariable}
includes={includes} includes={includes}
minimumFieldsRequiredMessage={minimumFieldsRequiredMessage}
setMinimumFieldsRequiredMessage={setMinimumFieldsRequiredMessage}
tableItems={includesTableItems} tableItems={includesTableItems}
unsupportedFieldsError={unsupportedFieldsError}
setUnsupportedFieldsError={setUnsupportedFieldsError}
loadingItems={loadingFieldOptions} loadingItems={loadingFieldOptions}
setFormState={setFormState} setFormState={setFormState}
/> />

View file

@ -15,13 +15,15 @@ import {
} from '@elastic/eui'; } from '@elastic/eui';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { useMlKibana } from '../../../../../contexts/kibana'; import { useMlKibana } from '../../../../../contexts/kibana';
import { getDataFrameAnalyticsProgressPhase } from '../../../analytics_management/components/analytics_list/common'; import {
getDataFrameAnalyticsProgressPhase,
DATA_FRAME_TASK_STATE,
} from '../../../analytics_management/components/analytics_list/common';
import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics'; import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics';
import { ml } from '../../../../../services/ml_api_service'; import { ml } from '../../../../../services/ml_api_service';
import { DataFrameAnalyticsId } from '../../../../common/analytics'; import { DataFrameAnalyticsId } from '../../../../common/analytics';
export const PROGRESS_REFRESH_INTERVAL_MS = 1000; export const PROGRESS_REFRESH_INTERVAL_MS = 1000;
const FAILED = 'failed';
export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) => { export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) => {
const [initialized, setInitialized] = useState<boolean>(false); const [initialized, setInitialized] = useState<boolean>(false);
@ -54,7 +56,7 @@ export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) =>
if (jobStats !== undefined) { if (jobStats !== undefined) {
const progressStats = getDataFrameAnalyticsProgressPhase(jobStats); const progressStats = getDataFrameAnalyticsProgressPhase(jobStats);
if (jobStats.state === FAILED) { if (jobStats.state === DATA_FRAME_TASK_STATE.FAILED) {
clearInterval(interval); clearInterval(interval);
setFailedJobMessage( setFailedJobMessage(
jobStats.failure_reason || jobStats.failure_reason ||
@ -70,8 +72,9 @@ export const ProgressStats: FC<{ jobId: DataFrameAnalyticsId }> = ({ jobId }) =>
setCurrentProgress(progressStats); setCurrentProgress(progressStats);
if ( if (
progressStats.currentPhase === progressStats.totalPhases && (progressStats.currentPhase === progressStats.totalPhases &&
progressStats.progress === 100 progressStats.progress === 100) ||
jobStats.state === DATA_FRAME_TASK_STATE.STOPPED
) { ) {
clearInterval(interval); clearInterval(interval);
} }