Skip to content

Commit

Permalink
[ML] Anomaly Detection: Fix jobs list default refresh. (elastic#57086)
Browse files Browse the repository at this point in the history
* [ML] Fix anomaly detection jobs list default refresh.

* [ML] Fix initial load of jobs list.

* [ML] Fix blockRefresh check.

* [ML] Fix blockRefresh check.

* [ML] Fix passing globalState between main tabs and retain custom refreshInterval when loading jobs list.
  • Loading branch information
walterra authored and jgowdyelastic committed Feb 11, 2020
1 parent c885cde commit 37a34cf
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
*/

import React, { FC, useState } from 'react';
import { encode } from 'rison-node';

import { EuiTabs, EuiTab, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { useUrlState } from '../../util/url_state';

import { TabId } from './navigation_menu';

export interface Tab {
Expand Down Expand Up @@ -65,6 +70,7 @@ const TAB_DATA: Record<TabId, TabData> = {
};

export const MainTabs: FC<Props> = ({ tabId, disableLinks }) => {
const [globalState] = useUrlState('_g');
const [selectedTabId, setSelectedTabId] = useState(tabId);
function onSelectedTabChanged(id: string) {
setSelectedTabId(id);
Expand All @@ -78,10 +84,13 @@ export const MainTabs: FC<Props> = ({ tabId, disableLinks }) => {
const id = tab.id;
const testSubject = TAB_DATA[id].testSubject;
const defaultPathId = TAB_DATA[id].pathId || id;
// globalState (e.g. selected jobs and time range) should be retained when changing pages.
// appState will not be considered.
const fullGlobalStateString = globalState !== undefined ? `?_g=${encode(globalState)}` : '';
return (
<EuiLink
data-test-subj={testSubject + (id === selectedTabId ? ' selected' : '')}
href={`#/${defaultPathId}`}
href={`#/${defaultPathId}${fullGlobalStateString}`}
key={`${id}-key`}
color="text"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ interface Duration {
end: string;
}

interface RefreshInterval {
pause: boolean;
value: number;
}

function getRecentlyUsedRangesFactory(timeHistory: TimeHistory) {
return function(): Duration[] {
return (
Expand All @@ -44,7 +49,7 @@ export const TopNav: FC = () => {
const [globalState, setGlobalState] = useUrlState('_g');
const getRecentlyUsedRanges = getRecentlyUsedRangesFactory(timeHistory);

const [refreshInterval, setRefreshInterval] = useState(
const [refreshInterval, setRefreshInterval] = useState<RefreshInterval>(
globalState?.refreshInterval ?? timefilter.getRefreshInterval()
);
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import React, { Component } from 'react';
import { timefilter } from 'ui/timefilter';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui';

Expand All @@ -26,13 +25,8 @@ import { UpgradeWarning } from '../../../../components/upgrade';
import { RefreshJobsListButton } from '../refresh_jobs_list_button';
import { isEqual } from 'lodash';

import {
DEFAULT_REFRESH_INTERVAL_MS,
DELETING_JOBS_REFRESH_INTERVAL_MS,
MINIMUM_REFRESH_INTERVAL_MS,
} from '../../../../../../common/constants/jobs_list';
import { DELETING_JOBS_REFRESH_INTERVAL_MS } from '../../../../../../common/constants/jobs_list';

let jobsRefreshInterval = null;
let deletingJobsRefreshTimeout = null;

// 'isManagementTable' bool prop to determine when to configure table for use in Kibana management page
Expand All @@ -58,21 +52,12 @@ export class JobsListView extends Component {
this.showDeleteJobModal = () => {};
this.showStartDatafeedModal = () => {};
this.showCreateWatchFlyout = () => {};

this.blockRefresh = false;
this.refreshIntervalSubscription = null;
}

componentDidMount() {
if (this.props.isManagementTable === true) {
this.refreshJobSummaryList(true);
} else {
timefilter.disableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();

this.initAutoRefresh();
this.initAutoRefreshUpdate();
this.refreshJobSummaryList(true);

if (this.props.isManagementTable !== true) {
// check to see if we need to open the start datafeed modal
// after the page has rendered. This will happen if the user
// has just created a job in the advanced wizard and selected to
Expand All @@ -81,59 +66,18 @@ export class JobsListView extends Component {
}
}

componentWillUnmount() {
if (this.props.isManagementTable === undefined) {
if (this.refreshIntervalSubscription) this.refreshIntervalSubscription.unsubscribe();
deletingJobsRefreshTimeout = null;
this.clearRefreshInterval();
}
}

initAutoRefresh() {
const { value } = timefilter.getRefreshInterval();
if (value === 0) {
// the auto refresher starts in an off state
// so switch it on and set the interval to 30s
timefilter.setRefreshInterval({
pause: false,
value: DEFAULT_REFRESH_INTERVAL_MS,
});
}

this.setAutoRefresh();
}

initAutoRefreshUpdate() {
// update the interval if it changes
this.refreshIntervalSubscription = timefilter.getRefreshIntervalUpdate$().subscribe({
next: () => this.setAutoRefresh(),
});
}

setAutoRefresh() {
const { value, pause } = timefilter.getRefreshInterval();
if (pause) {
this.clearRefreshInterval();
} else {
this.setRefreshInterval(value);
componentDidUpdate(prevProps) {
if (prevProps.lastRefresh !== this.props.lastRefresh) {
this.refreshJobSummaryList();
}
// force load the jobs list when the refresh interval changes
this.refreshJobSummaryList(true);
}

setRefreshInterval(interval) {
this.clearRefreshInterval();
if (interval >= MINIMUM_REFRESH_INTERVAL_MS) {
this.blockRefresh = false;
jobsRefreshInterval = setInterval(() => this.refreshJobSummaryList(), interval);
componentWillUnmount() {
if (this.props.isManagementTable === undefined) {
deletingJobsRefreshTimeout = null;
}
}

clearRefreshInterval() {
this.blockRefresh = true;
clearInterval(jobsRefreshInterval);
}

openAutoStartDatafeedModal() {
const job = checkForAutoStartDatafeed();
if (job !== undefined) {
Expand Down Expand Up @@ -272,7 +216,7 @@ export class JobsListView extends Component {
};

async refreshJobSummaryList(forceRefresh = false) {
if (forceRefresh === true || this.blockRefresh === false) {
if (forceRefresh === true || this.props.blockRefresh !== true) {
// Set loading to true for jobs_list table for initial job loading
if (this.state.loading === null) {
this.setState({ loading: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import { NavigationMenu } from '../../components/navigation_menu';
// @ts-ignore
import { JobsListView } from './components/jobs_list_view';

export const JobsPage: FC<{ props?: any }> = props => {
interface JobsPageProps {
blockRefresh?: boolean;
isManagementTable?: boolean;
isMlEnabledInSpace?: boolean;
lastRefresh?: number;
}

export const JobsPage: FC<JobsPageProps> = props => {
return (
<div data-test-subj="mlPageJobManagement">
<NavigationMenu tabId="jobs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { FC } from 'react';
import React, { useEffect, FC } from 'react';
import { useObservable } from 'react-use';
import { i18n } from '@kbn/i18n';
import { timefilter } from 'ui/timefilter';
import { DEFAULT_REFRESH_INTERVAL_MS } from '../../../../common/constants/jobs_list';
import { mlTimefilterRefresh$ } from '../../services/timefilter_refresh_service';
import { useUrlState } from '../../util/url_state';
import { MlRoute, PageLoader, PageProps } from '../router';
import { useResolver } from '../use_resolver';
import { basicResolvers } from '../resolvers';
Expand All @@ -32,9 +37,31 @@ export const jobListRoute: MlRoute = {
const PageWrapper: FC<PageProps> = ({ config, deps }) => {
const { context } = useResolver(undefined, undefined, config, basicResolvers(deps));

const [globalState, setGlobalState] = useUrlState('_g');

const mlTimefilterRefresh = useObservable(mlTimefilterRefresh$);
const lastRefresh = mlTimefilterRefresh?.lastRefresh ?? 0;
const refreshValue = globalState?.refreshInterval?.value ?? 0;
const refreshPause = globalState?.refreshInterval?.pause ?? true;
const blockRefresh = refreshValue === 0 || refreshPause === true;

useEffect(() => {
timefilter.disableTimeRangeSelector();
timefilter.enableAutoRefreshSelector();

// If the refreshInterval defaults to 0s/pause=true, set it to 30s/pause=false,
// otherwise pass on the globalState's settings to the date picker.
const refreshInterval =
refreshValue === 0 && refreshPause === true
? { pause: false, value: DEFAULT_REFRESH_INTERVAL_MS }
: { pause: refreshPause, value: refreshValue };
setGlobalState({ refreshInterval });
timefilter.setRefreshInterval(refreshInterval);
}, []);

return (
<PageLoader context={context}>
<JobsPage />
<JobsPage blockRefresh={blockRefresh} lastRefresh={lastRefresh} />
</PageLoader>
);
};

0 comments on commit 37a34cf

Please sign in to comment.