-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix flaky histogram when an adhoc data view is being edited #194904
Changes from 6 commits
bf323b8
036538a
7d4e3da
d574963
7726c7d
4cfc4f3
68a2478
89fdf5b
7ea856d
c0a6422
6d48b5c
39264c8
92eb2e4
3ceb8d6
b04350b
6b45e1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ | |
*/ | ||
|
||
import React, { useCallback, useEffect, useMemo, useRef } from 'react'; | ||
import { type DataView, DataViewType } from '@kbn/data-views-plugin/public'; | ||
import { DataViewType } from '@kbn/data-views-plugin/public'; | ||
import { DataViewPickerProps } from '@kbn/unified-search-plugin/public'; | ||
import { ENABLE_ESQL } from '@kbn/esql-utils'; | ||
import { TextBasedLanguages } from '@kbn/esql-utils'; | ||
|
@@ -20,7 +20,6 @@ import { useDiscoverServices } from '../../../../hooks/use_discover_services'; | |
import type { DiscoverStateContainer } from '../../state_management/discover_state'; | ||
import { onSaveSearch } from './on_save_search'; | ||
import { useDiscoverCustomization } from '../../../../customizations'; | ||
import { addLog } from '../../../../utils/add_log'; | ||
import { useAppStateSelector } from '../../state_management/discover_app_state_container'; | ||
import { useDiscoverTopNav } from './use_discover_topnav'; | ||
import { useIsEsqlMode } from '../../hooks/use_is_esql_mode'; | ||
|
@@ -46,15 +45,8 @@ export const DiscoverTopNav = ({ | |
onCancelClick, | ||
}: DiscoverTopNavProps) => { | ||
const services = useDiscoverServices(); | ||
const { | ||
dataViewEditor, | ||
navigation, | ||
dataViewFieldEditor, | ||
data, | ||
uiSettings, | ||
dataViews, | ||
setHeaderActionMenu, | ||
} = services; | ||
const { dataViewEditor, navigation, dataViewFieldEditor, data, uiSettings, setHeaderActionMenu } = | ||
services; | ||
const query = useAppStateSelector((state) => state.query); | ||
const adHocDataViews = useInternalStateSelector((state) => state.adHocDataViews); | ||
const dataView = useInternalStateSelector((state) => state.dataView!); | ||
|
@@ -122,23 +114,6 @@ export const DiscoverTopNav = ({ | |
}); | ||
}, [dataViewEditor, stateContainer]); | ||
|
||
const onEditDataView = useCallback( | ||
async (editedDataView: DataView) => { | ||
if (editedDataView.isPersisted()) { | ||
// Clear the current data view from the cache and create a new instance | ||
// of it, ensuring we have a new object reference to trigger a re-render | ||
dataViews.clearInstanceCache(editedDataView.id); | ||
stateContainer.actions.setDataView(await dataViews.create(editedDataView.toSpec(), true)); | ||
} else { | ||
await stateContainer.actions.updateAdHocDataViewId(); | ||
} | ||
stateContainer.actions.loadDataViewList(); | ||
addLog('[DiscoverTopNav] onEditDataView triggers data fetching'); | ||
stateContainer.dataState.fetch(); | ||
}, | ||
[dataViews, stateContainer.actions, stateContainer.dataState] | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems we had this code already in our state container without using it |
||
|
||
const updateSavedQueryId = (newSavedQueryId: string | undefined) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We were already having the same code in our state container, time use stateContainer.actions.onDataViewEdited instead of this code |
||
const { appState } = stateContainer; | ||
if (newSavedQueryId) { | ||
|
@@ -221,14 +196,13 @@ export const DiscoverTopNav = ({ | |
textBasedLanguages: supportedTextBasedLanguages, | ||
adHocDataViews, | ||
savedDataViews, | ||
onEditDataView, | ||
onEditDataView: stateContainer.actions.onDataViewEdited, | ||
}; | ||
}, [ | ||
adHocDataViews, | ||
addField, | ||
createNewDataView, | ||
dataView, | ||
onEditDataView, | ||
savedDataViews, | ||
stateContainer, | ||
uiSettings, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import { reportPerformanceMetricEvent } from '@kbn/ebt-tools'; | |
import { withSuspense } from '@kbn/shared-ux-utility'; | ||
import { getInitialESQLQuery } from '@kbn/esql-utils'; | ||
import { ESQL_TYPE } from '@kbn/data-view-utils'; | ||
import { useInternalStateSelector } from './state_management/discover_internal_state_container'; | ||
import { useUrl } from './hooks/use_url'; | ||
import { useDiscoverStateContainer } from './hooks/use_discover_state_container'; | ||
import { MainHistoryLocationState } from '../../../common'; | ||
|
@@ -85,7 +86,6 @@ export function DiscoverMainRoute({ | |
stateContainer, | ||
}); | ||
const [error, setError] = useState<Error>(); | ||
const [loading, setLoading] = useState(true); | ||
const [hasESData, setHasESData] = useState(false); | ||
const [hasUserDataView, setHasUserDataView] = useState(false); | ||
const [showNoDataPage, setShowNoDataPage] = useState<boolean>(false); | ||
|
@@ -156,9 +156,9 @@ export function DiscoverMainRoute({ | |
initialAppState, | ||
}: { nextDataView?: DataView; initialAppState?: LoadParams['initialAppState'] } = {}) => { | ||
const loadSavedSearchStartTime = window.performance.now(); | ||
setLoading(true); | ||
stateContainer.actions.setIsLoading(true); | ||
if (!nextDataView && !(await checkData())) { | ||
setLoading(false); | ||
stateContainer.actions.setIsLoading(false); | ||
return; | ||
} | ||
try { | ||
|
@@ -181,7 +181,7 @@ export function DiscoverMainRoute({ | |
|
||
setBreadcrumbs({ services, titleBreadcrumbText: currentSavedSearch?.title ?? undefined }); | ||
} | ||
setLoading(false); | ||
stateContainer.actions.setIsLoading(false); | ||
if (services.analytics) { | ||
const loadSavedSearchDuration = window.performance.now() - loadSavedSearchStartTime; | ||
reportPerformanceMetricEvent(services.analytics, { | ||
|
@@ -215,7 +215,7 @@ export function DiscoverMainRoute({ | |
}, | ||
[ | ||
checkData, | ||
stateContainer.actions, | ||
stateContainer, | ||
savedSearchId, | ||
historyLocationState?.dataViewSpec, | ||
customizationContext.displayMode, | ||
|
@@ -231,8 +231,7 @@ export function DiscoverMainRoute({ | |
|
||
useEffect(() => { | ||
if (!isCustomizationServiceInitialized) return; | ||
|
||
setLoading(true); | ||
stateContainer.actions.setIsLoading(true); | ||
setHasESData(false); | ||
setHasUserDataView(false); | ||
setShowNoDataPage(false); | ||
|
@@ -258,13 +257,13 @@ export function DiscoverMainRoute({ | |
const onDataViewCreated = useCallback( | ||
async (nextDataView: unknown) => { | ||
if (nextDataView) { | ||
setLoading(true); | ||
stateContainer.actions.setIsLoading(true); | ||
setShowNoDataPage(false); | ||
setError(undefined); | ||
await loadSavedSearch({ nextDataView: nextDataView as DataView }); | ||
} | ||
}, | ||
[loadSavedSearch] | ||
[loadSavedSearch, stateContainer] | ||
); | ||
|
||
const onESQLNavigationComplete = useCallback(async () => { | ||
|
@@ -325,14 +324,8 @@ export function DiscoverMainRoute({ | |
); | ||
} | ||
|
||
if (loading) { | ||
return loadingIndicator; | ||
} | ||
|
||
return <DiscoverMainAppMemoized stateContainer={stateContainer} />; | ||
}, [ | ||
loading, | ||
loadingIndicator, | ||
noDataDependencies, | ||
onDataViewCreated, | ||
onESQLNavigationComplete, | ||
|
@@ -354,20 +347,40 @@ export function DiscoverMainRoute({ | |
return ( | ||
<DiscoverCustomizationProvider value={customizationService}> | ||
<DiscoverMainProvider value={stateContainer}> | ||
<> | ||
<DiscoverTopNavInline | ||
stateContainer={stateContainer} | ||
hideNavMenuItems={loading || showNoDataPage} | ||
/> | ||
{mainContent} | ||
</> | ||
<DiscoverMainLoading | ||
mainContent={mainContent} | ||
showNoDataPage={showNoDataPage} | ||
stateContainer={stateContainer} | ||
/> | ||
</DiscoverMainProvider> | ||
</DiscoverCustomizationProvider> | ||
); | ||
} | ||
// eslint-disable-next-line import/no-default-export | ||
export default DiscoverMainRoute; | ||
|
||
export function DiscoverMainLoading({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since the loading state now is in the stateContainer, we need to have the state container in context so it's provided, therefore this change. This could be seen as first part of refactoring this file, which could use some love |
||
stateContainer, | ||
showNoDataPage, | ||
mainContent, | ||
}: { | ||
stateContainer: DiscoverStateContainer; | ||
showNoDataPage: boolean; | ||
mainContent: JSX.Element; | ||
}) { | ||
const loading = useInternalStateSelector((state) => state.isLoading); | ||
|
||
return ( | ||
<> | ||
<DiscoverTopNavInline | ||
stateContainer={stateContainer} | ||
hideNavMenuItems={showNoDataPage || loading} | ||
/> | ||
{loading && !showNoDataPage ? <LoadingIndicator /> : mainContent} | ||
</> | ||
); | ||
} | ||
|
||
function getLoadParamsForNewSearch(stateContainer: DiscoverStateContainer): { | ||
nextDataView: LoadParams['dataView']; | ||
initialAppState: LoadParams['initialAppState']; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -210,6 +210,11 @@ export interface DiscoverStateContainer { | |
* @param dataView | ||
*/ | ||
setDataView: (dataView: DataView) => void; | ||
/** | ||
* Set Discover to loading state on the highest level, this cleans up all internal UI state | ||
* @param value | ||
*/ | ||
setIsLoading: (value: boolean) => void; | ||
/** | ||
* Undo changes made to the saved search, e.g. when the user triggers the "Reset search" button | ||
*/ | ||
|
@@ -407,17 +412,24 @@ export function getDiscoverStateContainer({ | |
} | ||
}; | ||
|
||
const setIsLoading = (value: boolean) => { | ||
internalStateContainer.transitions.setIsLoading(value); | ||
}; | ||
|
||
const onDataViewEdited = async (editedDataView: DataView) => { | ||
setIsLoading(true); | ||
const edited = editedDataView.id; | ||
if (editedDataView.isPersisted()) { | ||
// Clear the current data view from the cache and create a new instance | ||
// of it, ensuring we have a new object reference to trigger a re-render | ||
services.dataViews.clearInstanceCache(editedDataView.id); | ||
services.dataViews.clearInstanceCache(edited); | ||
setDataView(await services.dataViews.create(editedDataView.toSpec(), true)); | ||
} else { | ||
await updateAdHocDataViewId(); | ||
} | ||
loadDataViewList(); | ||
await loadDataViewList(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I first thought, ha! got you flaky test monster, a missing await, however it didn't help, but it should be changed anyway |
||
addLog('[getDiscoverStateContainer] onDataViewEdited triggers data fetching'); | ||
internalStateContainer.transitions.setIsLoading(false); | ||
fetchData(); | ||
}; | ||
|
||
|
@@ -591,6 +603,7 @@ export function getDiscoverStateContainer({ | |
onDataViewCreated, | ||
onDataViewEdited, | ||
onOpenSavedSearch, | ||
setIsLoading, | ||
transitionFromESQLToDataView, | ||
transitionFromDataViewToESQL, | ||
onUpdateQuery, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dej611 this needs an issue as follow up to investigate