[arvados-workbench2] created: 2.4.0-327-g9700822f
git repository hosting
git at public.arvados.org
Fri Oct 28 13:26:07 UTC 2022
at 9700822f13c7f81939e8344e799d2d30f749c2f7 (commit)
commit 9700822f13c7f81939e8344e799d2d30f749c2f7
Author: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
Date: Fri Oct 28 15:25:18 2022 +0200
19275: Fix for race conditions in the full text search bar
Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla at contractors.roche.com>
diff --git a/src/services/common-service/common-service.ts b/src/services/common-service/common-service.ts
index bdae87ab..b8e7dc67 100644
--- a/src/services/common-service/common-service.ts
+++ b/src/services/common-service/common-service.ts
@@ -87,11 +87,13 @@ export class CommonService<T> {
return mapKeys ? CommonService.mapResponseKeys(response) : response.data;
})
.catch(({ response }) => {
- actions.progressFn(reqId, false);
- const errors = CommonService.mapResponseKeys(response) as Errors;
- errors.status = response.status;
- actions.errorFn(reqId, errors, showErrors);
- throw errors;
+ if (response) {
+ actions.progressFn(reqId, false);
+ const errors = CommonService.mapResponseKeys(response) as Errors;
+ errors.status = response.status;
+ actions.errorFn(reqId, errors, showErrors);
+ throw errors;
+ }
});
}
diff --git a/src/services/groups-service/groups-service.ts b/src/services/groups-service/groups-service.ts
index dc6a798c..b69483cb 100644
--- a/src/services/groups-service/groups-service.ts
+++ b/src/services/groups-service/groups-service.ts
@@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: AGPL-3.0
+import { CancelToken } from 'axios';
import { snakeCase, camelCase } from "lodash";
import { CommonResourceService } from 'services/common-service/common-resource-service';
import { ListResults, ListArguments } from 'services/common-service/common-service';
@@ -41,7 +42,7 @@ export class GroupsService<T extends GroupResource = GroupResource> extends Tras
super(serverApi, "groups", actions);
}
- async contents(uuid: string, args: ContentsArguments = {}, session?: Session): Promise<ListResults<GroupContentsResource>> {
+ async contents(uuid: string, args: ContentsArguments = {}, session?: Session, cancelToken?: CancelToken): Promise<ListResults<GroupContentsResource>> {
const { filters, order, ...other } = args;
const params = {
...other,
@@ -56,6 +57,10 @@ export class GroupsService<T extends GroupResource = GroupResource> extends Tras
cfg.headers = { 'Authorization': 'Bearer ' + session.token };
}
+ if (cancelToken) {
+ cfg.cancelToken = cancelToken;
+ }
+
const response = await CommonResourceService.defaultResponse(
this.serverApi.get(this.resourceType + pathUrl, cfg), this.actions, false
);
diff --git a/src/store/search-bar/search-bar-actions.ts b/src/store/search-bar/search-bar-actions.ts
index 7d76ec69..8b03ddd7 100644
--- a/src/store/search-bar/search-bar-actions.ts
+++ b/src/store/search-bar/search-bar-actions.ts
@@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: AGPL-3.0
+import axios from "axios";
import { ofType, unionize, UnionOf } from "common/unionize";
import { GroupContentsResource, GroupContentsResourcePrefix } from 'services/groups-service/groups-service';
import { Dispatch } from 'redux';
@@ -62,13 +63,13 @@ export const loadRecentQueries = () =>
return recentQueries;
};
-export const searchData = (searchValue: string) =>
+export const searchData = (searchValue: string, useCancel = false) =>
async (dispatch: Dispatch, getState: () => RootState) => {
const currentView = getState().searchBar.currentView;
dispatch(searchResultsPanelActions.CLEAR());
dispatch(searchBarActions.SET_SEARCH_VALUE(searchValue));
if (searchValue.length > 0) {
- dispatch<any>(searchGroups(searchValue, 5));
+ dispatch<any>(searchGroups(searchValue, 5, useCancel));
if (currentView === SearchView.BASIC) {
dispatch(searchBarActions.CLOSE_SEARCH_VIEW());
dispatch(navigateToSearchResults(searchValue));
@@ -203,26 +204,41 @@ export const submitData = (event: React.FormEvent<HTMLFormElement>) =>
}
};
-
-const searchGroups = (searchValue: string, limit: number) =>
+let cancelTokens: any[] = [];
+const searchGroups = (searchValue: string, limit: number, useCancel = false) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
const currentView = getState().searchBar.currentView;
- if (searchValue || currentView === SearchView.ADVANCED) {
- const { cluster: clusterId } = getAdvancedDataFromQuery(searchValue);
- const sessions = getSearchSessions(clusterId, getState().auth.sessions);
- const lists: ListResults<GroupContentsResource>[] = await Promise.all(sessions.map(session => {
- const filters = queryToFilters(searchValue, session.apiRevision);
- return services.groupsService.contents('', {
- filters,
- limit,
- recursive: true
- }, session);
- }));
-
- const items = lists.reduce((items, list) => items.concat(list.items), [] as GroupContentsResource[]);
- dispatch(searchBarActions.SET_SEARCH_RESULTS(items));
+ if (cancelTokens.length > 0 && useCancel) {
+ cancelTokens.forEach(cancelToken => (cancelToken as any).cancel('New search request triggered.'));
+ cancelTokens = [];
}
+
+ setTimeout(async () => {
+ if (searchValue || currentView === SearchView.ADVANCED) {
+ const { cluster: clusterId } = getAdvancedDataFromQuery(searchValue);
+ const sessions = getSearchSessions(clusterId, getState().auth.sessions);
+ const lists: ListResults<GroupContentsResource>[] = await Promise.all(sessions.map((session, index) => {
+ cancelTokens.push(axios.CancelToken.source());
+ const filters = queryToFilters(searchValue, session.apiRevision);
+ return services.groupsService.contents('', {
+ filters,
+ limit,
+ recursive: true
+ }, session, cancelTokens[index].token);
+ }));
+
+ cancelTokens = [];
+
+ const items = lists.reduce((items, list) => items.concat(list.items), [] as GroupContentsResource[]);
+
+ if (lists.filter(list => !!(list as any).items).length !== lists.length) {
+ dispatch(searchBarActions.SET_SEARCH_RESULTS([]));
+ } else {
+ dispatch(searchBarActions.SET_SEARCH_RESULTS(items));
+ }
+ }
+ }, 10);
};
const buildQueryFromKeyMap = (data: any, keyMap: string[][]) => {
diff --git a/src/views-components/search-bar/search-bar.tsx b/src/views-components/search-bar/search-bar.tsx
index 327644ed..6a4d2a62 100644
--- a/src/views-components/search-bar/search-bar.tsx
+++ b/src/views-components/search-bar/search-bar.tsx
@@ -38,7 +38,7 @@ const mapStateToProps = ({ searchBar, form }: RootState): SearchBarDataProps =>
};
const mapDispatchToProps = (dispatch: Dispatch): SearchBarActionProps => ({
- onSearch: (valueSearch: string) => dispatch<any>(searchData(valueSearch)),
+ onSearch: (valueSearch: string) => dispatch<any>(searchData(valueSearch, true)),
onChange: (event: React.ChangeEvent<HTMLInputElement>) => dispatch<any>(changeData(event.target.value)),
onSetView: (currentView: string) => dispatch(goToView(currentView)),
onSubmit: (event: React.FormEvent<HTMLFormElement>) => dispatch<any>(submitData(event)),
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list