Chore: Refactor Search out-of-order fix (#68445)

This commit is contained in:
Josh Hunt
2023-05-18 16:14:59 +01:00
committed by GitHub
parent 560f49b3dc
commit 9e4b532979
2 changed files with 20 additions and 14 deletions
@@ -83,7 +83,7 @@ export async function getSearchResultActions(searchQuery: string): Promise<Comma
export function useSearchResults(searchQuery: string, isShowing: boolean) {
const [searchResults, setSearchResults] = useState<CommandPaletteAction[]>([]);
const [isFetchingSearchResults, setIsFetchingSearchResults] = useState(false);
const lastRequestTimestamp = useRef<number>();
const lastSearchTimestamp = useRef<number>(0);
// Hit dashboards API
useEffect(() => {
@@ -91,19 +91,20 @@ export function useSearchResults(searchQuery: string, isShowing: boolean) {
if (isShowing && searchQuery.length > 0) {
setIsFetchingSearchResults(true);
debouncedSearch(searchQuery).then((resultActions) => {
// Only update the state if this is the most recent request
// We don't need to worry about clearing the isFetching state either
// If there's a later request in progress, this will clear it for us
if (!lastRequestTimestamp.current || timestamp > lastRequestTimestamp.current) {
// Only keep the results if it's was issued after the most recently resolved search.
// This prevents results showing out of order if first request is slower than later ones.
// We don't need to worry about clearing the isFetching state either - if there's a later
// request in progress, this will clear it for us
if (timestamp > lastSearchTimestamp.current) {
setSearchResults(resultActions);
setIsFetchingSearchResults(false);
lastRequestTimestamp.current = timestamp;
lastSearchTimestamp.current = timestamp;
}
});
} else {
setSearchResults([]);
setIsFetchingSearchResults(false);
lastRequestTimestamp.current = timestamp;
lastSearchTimestamp.current = timestamp;
}
}, [isShowing, searchQuery]);
@@ -39,7 +39,8 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
updateLocation = debounce((query) => locationService.partial(query, true), 300);
doSearchWithDebounce = debounce(() => this.doSearch(), 300);
lastQuery?: SearchQuery;
lastSearchPromise: Promise<void> = Promise.resolve();
lastSearchTimestamp = 0;
initStateFromUrl(folderUid?: string, doInitialSearch = true) {
const stateFromUrl = parseRouteParams(locationService.getSearchObject());
@@ -227,20 +228,24 @@ export class SearchStateManager extends StateManagerBase<SearchState> {
const searcher = getGrafanaSearcher();
// Issue this search now, but wait until previous searches have resolved to update it in the state
const searchTimestamp = Date.now();
const searchPromise = this.state.starred ? searcher.starred(this.lastQuery) : searcher.search(this.lastQuery);
this.lastSearchPromise = this.lastSearchPromise
.then(() => searchPromise)
.then((result) => this.setState({ result, loading: false }))
searchPromise
.then((result) => {
// Only keep the results if it's was issued after the most recently resolved search.
// This prevents results showing out of order if first request is slower than later ones
if (searchTimestamp > this.lastSearchTimestamp) {
this.setState({ result, loading: false });
this.lastSearchTimestamp = searchTimestamp;
}
})
.catch((error) => {
reportSearchFailedQueryInteraction(this.state.eventTrackingNamespace, {
...trackingInfo,
error: error?.message,
});
this.setState({ loading: false });
return Promise.resolve(); // make sure this.lastSearchPromise is always resolved
});
}