Skip to content
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

Feature/speed up page navigation #291

Merged
merged 3 commits into from Jul 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion ngrinder-controller/pom.xml
Expand Up @@ -278,7 +278,11 @@
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.2.Final</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.2.2.Final</version>
</dependency>

<!-- AspectJ dependencies -->
<dependency>
Expand Down
@@ -1,4 +1,4 @@
/*
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -9,7 +9,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
package org.ngrinder.perftest.controller;

Expand Down Expand Up @@ -137,11 +137,11 @@ public String getAll(User user, @RequestParam(required = false) String query,
@PageableDefault(page = 0, size = 10) Pageable pageable, ModelMap model) {
pageable = new PageRequest(pageable.getPageNumber(), pageable.getPageSize(),
defaultIfNull(pageable.getSort(),
new Sort(Direction.DESC, "lastModifiedDate")));
new Sort(Direction.DESC, "id")));
Page<PerfTest> tests = perfTestService.getPagedAll(user, query, tag, queryFilter, pageable);
if (tests.getNumberOfElements() == 0) {
pageable = new PageRequest(0, pageable.getPageSize(), defaultIfNull(pageable.getSort(),
new Sort(Direction.DESC, "lastModifiedDate")));
new Sort(Direction.DESC, "id")));
tests = perfTestService.getPagedAll(user, query, tag, queryFilter, pageable);
}
annotateDateMarker(tests);
Expand Down
@@ -1,4 +1,4 @@
/*
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -9,7 +9,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
package org.ngrinder.user.controller;

Expand Down Expand Up @@ -162,7 +162,7 @@ public String getOne(@PathVariable final String userId, ModelMap model) {
@RequestMapping("/profile")
public String getOne(User user, ModelMap model) {
checkNotEmpty(user.getUserId(), "UserID should not be NULL!");
User one = userService.getOne(user.getUserId());
User one = userService.getOneWithFollowers(user.getUserId());
model.addAttribute("user", one);
model.addAttribute("allowPasswordChange", !config.isDemo());
model.addAttribute("allowRoleChange", false);
Expand Down Expand Up @@ -261,18 +261,16 @@ public String switchOptions(User user,


private List<UserSearchResult> getSwitchableUsers(User user, String keywords) {
List<UserSearchResult> result = newArrayList();
if (user.getRole().hasPermission(Permission.SWITCH_TO_ANYONE)) {
List<UserSearchResult> result = newArrayList();
for (User each : userService.getPagedAll(keywords, new PageRequest(0, 10))) {
result.add(new UserSearchResult(each));
}
return result;
} else {
User currUser = userService.getOne(user.getUserId());
for (User each : currUser.getOwners()) {
result.add(new UserSearchResult(each));
}
return userService.getSharedUser(user);
}
return result;

}


Expand Down Expand Up @@ -415,8 +413,8 @@ public HttpEntity<String> delete(User user, @PathVariable("userId") String userI
public HttpEntity<String> search(User user, @PageableDefault Pageable pageable,
@RequestParam(required = true) String keywords) {
pageable = new PageRequest(pageable.getPageNumber(), pageable.getPageSize(),
defaultIfNull(pageable.getSort(),
new Sort(Direction.ASC, "userName")));
defaultIfNull(pageable.getSort(),
new Sort(Direction.ASC, "userName")));
Page<User> pagedUser = userService.getPagedAll(keywords, pageable);
List<UserSearchResult> result = newArrayList();
for (User each : pagedUser) {
Expand Down
@@ -1,4 +1,4 @@
/*
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -9,7 +9,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
package org.ngrinder.user.service;

Expand All @@ -24,6 +24,7 @@
import org.ngrinder.script.service.FileEntryService;
import org.ngrinder.security.SecuredUser;
import org.ngrinder.service.AbstractUserService;
import org.ngrinder.user.controller.UserController;
import org.ngrinder.user.repository.UserRepository;
import org.ngrinder.user.repository.UserSpecification;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -79,9 +80,12 @@ public class UserService extends AbstractUserService {

private Cache userCache;

private Cache userModelCache;

@PostConstruct
public void init() {
userCache = cacheManager.getCache("users");
userModelCache = cacheManager.getCache("org.ngrinder.model.User");
}

/**
Expand All @@ -97,6 +101,20 @@ public User getOne(String userId) {
return userRepository.findOneByUserId(userId);
}

/**
* Get user by user id with followers.
*
* @param userId user id
* @return user
*/
@Transactional
public User getOneWithFollowers(String userId) {
User one = userRepository.findOneByUserId(userId);
one.getFollowers().size();
return one;
}


/**
* Encoding given user's password.
*
Expand Down Expand Up @@ -147,6 +165,7 @@ public User saveWithoutPasswordEncoding(User user) {
if (existingFollowers != null) {
for (User eachFollower : existingFollowers) {
userCache.evict(eachFollower.getUserId());
userModelCache.evict(eachFollower.getId());
}
}
user = existing.merge(user);
Expand All @@ -155,6 +174,7 @@ public User saveWithoutPasswordEncoding(User user) {
// Then expires new followers so that new followers info can be loaded.
for (User eachFollower : followers) {
userCache.evict(eachFollower.getUserId());
userModelCache.evict(eachFollower.getId());
}
prepareUserEnv(createdUser);
return createdUser;
Expand Down Expand Up @@ -270,4 +290,13 @@ public User createUser(User user) {
}


@Transactional
public List<UserController.UserSearchResult> getSharedUser(User user) {
List<UserController.UserSearchResult> result = new ArrayList<UserController.UserSearchResult>();
User currUser = getOne(user.getUserId());
for (User each : currUser.getOwners()) {
result.add(new UserController.UserSearchResult(each));
}
return result;
}
}
Expand Up @@ -7,6 +7,9 @@
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.connection.release_mode" value="on_close"/>
<property name="hibernate.max_fetch_depth" value="0"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
</properties>
</persistence-unit>
</persistence>
15 changes: 11 additions & 4 deletions ngrinder-controller/src/main/resources/ehcache-dist.xml
Expand Up @@ -16,22 +16,29 @@
cluster. -->


<cache name="users" maxElementsInMemory="100" eternal="false"
overflowToDisk="false" timeToIdleSeconds="30" timeToLiveSeconds="30">
<cache name="users" maxElementsInMemory="1000" eternal="false"
overflowToDisk="false" timeToIdleSeconds="60" timeToLiveSeconds="60">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=false, replicatePuts=false, replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>

<cache name="file_entries" maxElementsInMemory="100"
<cache name="org.ngrinder.model.User" maxElementsInMemory="1000" eternal="false"
overflowToDisk="false" timeToIdleSeconds="60" timeToLiveSeconds="60">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=false, replicatePuts=false, replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>

<cache name="file_entries" maxElementsInMemory="1000"
eternal="false" overflowToDisk="false" timeToIdleSeconds="6000"
timeToLiveSeconds="6000">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=false, replicateUpdates=false, replicateUpdatesViaCopy=false, replicateRemovals=true"/>
</cache>

<cache name="regions" maxElementsInMemory="100" overflowToDisk="false" eternal="false" timeToLiveSeconds="30">
<cache name="regions" maxElementsInMemory="1000" overflowToDisk="false" eternal="false" timeToLiveSeconds="30">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=false"/>
Expand Down
5 changes: 5 additions & 0 deletions ngrinder-controller/src/main/resources/ehcache.xml
Expand Up @@ -7,6 +7,11 @@
<cache name="users" maxElementsInMemory="100" eternal="false" overflowToDisk="false" timeToIdleSeconds="30"
timeToLiveSeconds="30"/>

<cache name="org.ngrinder.model.User" maxElementsInMemory="100" eternal="false"
overflowToDisk="false" timeToIdleSeconds="1" timeToLiveSeconds="1">
</cache>


<cache name="file_entries" maxElementsInMemory="100" eternal="false" overflowToDisk="false"
timeToIdleSeconds="6000" timeToLiveSeconds="6000"/>
<cache name="right_panel_entries" maxElementsInMemory="2" eternal="false" overflowToDisk="false"
Expand Down
15 changes: 9 additions & 6 deletions ngrinder-core/src/main/java/org/ngrinder/model/User.java
@@ -1,4 +1,4 @@
/*
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
Expand All @@ -9,12 +9,13 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
package org.ngrinder.model;

import com.google.gson.annotations.Expose;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Type;

import javax.persistence.*;
Expand All @@ -29,6 +30,8 @@
* @since 3.0
*/
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "NUSER")
public class User extends BaseModel<User> {

Expand Down Expand Up @@ -91,14 +94,14 @@ public class User extends BaseModel<User> {
@Transient
private User ownerUser;

@ManyToMany(fetch = FetchType.EAGER)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "SHARED_USER", joinColumns = @JoinColumn(name = "owner_id"), // LF
inverseJoinColumns = @JoinColumn(name = "follow_id"))
inverseJoinColumns = @JoinColumn(name = "follow_id"))
private List<User> followers;

@ManyToMany(fetch = FetchType.EAGER)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "SHARED_USER", joinColumns = @JoinColumn(name = "follow_id"), // LF
inverseJoinColumns = @JoinColumn(name = "owner_id"))
inverseJoinColumns = @JoinColumn(name = "owner_id"))
private List<User> owners;

/**
Expand Down