Skip to content

Commit

Permalink
Fixed ListUserItemsRequest performance (#1035)
Browse files Browse the repository at this point in the history
  • Loading branch information
reisfmb committed May 6, 2022
1 parent 00c2c0f commit b7eeb06
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 12 deletions.
19 changes: 18 additions & 1 deletion src/main/resources/assets/js/app/browse/UserItemsTreeGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {i18n} from 'lib-admin-ui/util/Messages';
import {ListPrincipalsKeysResult, ListPrincipalsNamesRequest} from '../../graphql/principal/ListPrincipalsNamesRequest';
import {DefaultErrorHandler} from 'lib-admin-ui/DefaultErrorHandler';
import {GetPrincipalsTotalRequest} from '../../graphql/principal/GetPrincipalsTotalRequest';
import {UserFilteredDataScrollEvent} from '../event/UserFilteredDataScrollEvent';
import {AppHelper} from 'lib-admin-ui/util/AppHelper';

export class UserItemsTreeGrid
extends TreeGrid<UserTreeGridItem> {
Expand Down Expand Up @@ -76,6 +78,17 @@ export class UserItemsTreeGrid
}

private initEventHandlers() {
const triggerFilteredDataScrollEvent = AppHelper.debounce(() => {

const currentNumberOfItems = this.getRoot().getCurrentRoot().getChildren().length;
const numberOfItemsToAdd = 30;
const nextNumberOfItems = currentNumberOfItems + numberOfItemsToAdd;

if(this.getGrid().getViewport().bottom === currentNumberOfItems){
new UserFilteredDataScrollEvent(nextNumberOfItems).fire();
}
}, 100);

BrowseFilterSearchEvent.on((event: BrowseFilterSearchEvent<PrincipalBrowseSearchData>) => {
const data = event.getData();
const items = data.getUserItems().map((userItem: UserItem) => {
Expand All @@ -85,10 +98,14 @@ export class UserItemsTreeGrid
this.searchTypes = data.getTypes();
this.filter(items);
this.notifyLoaded();

this.getGrid().subscribeOnScroll(triggerFilteredDataScrollEvent);
});

BrowseFilterResetEvent.on(() => {
this.resetFilter();

this.getGrid().unsubscribeOnScroll(triggerFilteredDataScrollEvent);
});

this.getGrid().subscribeOnDblClick((event, data) => {
Expand Down Expand Up @@ -251,7 +268,7 @@ export class UserItemsTreeGrid
}

private fetchFilteredItems(): Q.Promise<UserTreeGridItem[]> {
return new ListUserItemsRequest().setTypes(this.searchTypes).setQuery(this.searchString).sendAndParse()
return new ListUserItemsRequest().setCount(100).setTypes(this.searchTypes).setQuery(this.searchString).sendAndParse()
.then((result) => {
return result.userItems.map(item => new UserTreeGridItemBuilder().setAny(item).build());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {i18n} from 'lib-admin-ui/util/Messages';
import {UserItem} from 'lib-admin-ui/security/UserItem';
import {SearchInputValues} from 'lib-admin-ui/query/SearchInputValues';
import {Exception} from 'lib-admin-ui/Exception';
import {UserFilteredDataScrollEvent} from '../../event/UserFilteredDataScrollEvent';

export class PrincipalBrowseFilterPanel
extends BrowseFilterPanel<UserTreeGridItem> {
Expand All @@ -30,11 +31,20 @@ export class PrincipalBrowseFilterPanel

this.fetchAndUpdateAggregations();
this.initHitsCounter();
this.initEventHandlers();
}

private initEventHandlers() {
UserFilteredDataScrollEvent.on((event) => {
const newCounterAfterScroll = event.getCount();
this.searchDataAndHandleResponse(newCounterAfterScroll);
});
}

private initHitsCounter() {
new ListUserItemsRequest().sendAndParse().then((result: ListUserItemsRequestResult) => {
this.updateHitsCounter(result.userItems ? result.userItems.length : 0, true);
// setCount(1): Only total is used, so there's no need to traverse everything.
new ListUserItemsRequest().setCount(1).sendAndParse().then((result: ListUserItemsRequestResult) => {
this.updateHitsCounter(result.total, true);
}).catch((reason: Error | Exception) => {
DefaultErrorHandler.handle(reason);
});
Expand Down Expand Up @@ -66,10 +76,10 @@ export class PrincipalBrowseFilterPanel
}

protected resetFacets(suppressEvent?: boolean, doResetAll?: boolean): Q.Promise<void> {
return new ListUserItemsRequest().sendAndParse().then((result: ListUserItemsRequestResult) => {
// setCount(1): Only total and aggregations are used, so there's no need to traverse everything.
return new ListUserItemsRequest().setCount(1).sendAndParse().then((result: ListUserItemsRequestResult) => {
return this.fetchAndUpdateAggregations().then(() => {
const userItems: UserItem[] = result.userItems;
this.updateHitsCounter(userItems ? userItems.length : 0, true);
this.updateHitsCounter(result.total, true);
this.toggleAggregationsVisibility(result.aggregations);

// then fire usual reset event with content grid reloading
Expand All @@ -91,12 +101,18 @@ export class PrincipalBrowseFilterPanel
.filter(type => type != null);
}

private searchDataAndHandleResponse(): Q.Promise<void> {
// setCount(100): Initially get only 100 users. The UserFilteredDataScrollEvent will request more if necessary.
private searchDataAndHandleResponse(count: number = 100): Q.Promise<void> {
const types: UserItemType[] = this.getCheckedTypes();
const searchString: string = this.getSearchInputValues().getTextSearchFieldValue();
const itemIds: string[] = this.getSelectedItemIds();

return new ListUserItemsRequest().setTypes(types).setQuery(searchString).setItems(itemIds).sendAndParse()
return new ListUserItemsRequest()
.setCount(count)
.setTypes(types)
.setQuery(searchString)
.setItems(itemIds)
.sendAndParse()
.then((result: ListUserItemsRequestResult) => {
this.handleDataSearchResult(result, types, searchString);
}).catch((reason: any) => {
Expand All @@ -109,7 +125,8 @@ export class PrincipalBrowseFilterPanel
const searchString: string = this.getSearchInputValues().getTextSearchFieldValue();
const itemIds: string[] = this.getSelectedItemIds();

return new ListUserItemsRequest().setTypes(types).setQuery(searchString).setItems(itemIds).sendAndParse()
// setCount(100): After refreshing get only 100 users.
return new ListUserItemsRequest().setCount(100).setTypes(types).setQuery(searchString).setItems(itemIds).sendAndParse()
.then((result: ListUserItemsRequestResult) => {
if (result.userItems.length > 0) {
this.handleDataSearchResult(result, types, searchString);
Expand All @@ -135,7 +152,7 @@ export class PrincipalBrowseFilterPanel

new BrowseFilterSearchEvent(new PrincipalBrowseSearchData(searchString, types, userItems)).fire();

this.updateHitsCounter(userItems ? userItems.length : 0, StringHelper.isBlank(searchString));
this.updateHitsCounter(result.total, StringHelper.isBlank(searchString));
this.toggleAggregationsVisibility(result.aggregations);
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {ClassHelper} from 'lib-admin-ui/ClassHelper';
import {Event} from 'lib-admin-ui/event/Event';

export class UserFilteredDataScrollEvent
extends Event {

private count: number;

constructor(count: number) {
super();
this.count = count;
}

public getCount(): number {
return this.count;
}

static on(handler: (event: UserFilteredDataScrollEvent) => void): void {
Event.bind(ClassHelper.getFullName(this), handler);
}

static un(handler?: (event: UserFilteredDataScrollEvent) => void): void {
Event.unbind(ClassHelper.getFullName(this), handler);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {ListItemsProperties, ListItemsRequest} from './ListItemsRequest';
// UserItems does not map "name" property. Missing type? or wrong graph query?
export type ListUserItemsRequestResult = {
total: number,
userItems: UserItem[],
userItems: UserItem[],
aggregations: BucketAggregation[]
};

Expand All @@ -37,7 +37,7 @@ interface ListUserItemsGraph {
description: string;
displayName: string;
}
}],
}],
aggregations: UserItemBucketAggregationJson[];
}
}
Expand All @@ -47,6 +47,15 @@ export class ListUserItemsRequest

private types: UserItemType[];

constructor(){
super();
}

setCount(value: number): ListUserItemsRequest {
this.count = value;
return this;
}

setTypes(types: UserItemType[]): ListUserItemsRequest {
this.types = types;
return this;
Expand Down

0 comments on commit b7eeb06

Please sign in to comment.