[Notice] Announcing the End of Demo Server [Read me]
이응준 2015-08-19
Merge branch 'perf/issue' into 'next'
from pull-request 1714

* perf/issue:
  perf: Avoid unnecessary permission check
  perf/user: Make hash() and equals() faster
  perf/issue: Improve performance using @Transactional

Reviewed-by: 채수원 
@41bf4b42a0a68e9f09cc39e1a68fb528a1856915
app/controllers/IssueApp.java
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
@@ -91,6 +91,7 @@
         return searchCondition.assigneeId == null && searchCondition.authorId == null && searchCondition.mentionId == null;
     }
 
+    @Transactional
     @IsAllowed(Operation.READ)
     public static Result issues(String ownerName, String projectName, String state, String format, int pageNum) throws WriteException, IOException {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
@@ -205,6 +206,7 @@
         return ok(listData);
     }
 
+    @Transactional
     @With(NullProjectCheckAction.class)
     public static Result issue(String ownerName, String projectName, Long number) {
         Project project = Project.findByOwnerAndProjectName(ownerName, projectName);
app/models/AbstractPosting.java
--- app/models/AbstractPosting.java
+++ app/models/AbstractPosting.java
@@ -222,13 +222,9 @@
         // default implementation for convenience
     }
 
-    /**
-     * @see {@link #getWatchers()}
-     * @see <a href="https://github.com/nforge/yobi/blob/master/docs/technical/watch.md>watch.md</a>
-     */
     @Transient
     public Set<User> getWatchers() {
-        return getWatchers(new HashSet<User>());
+        return getWatchers(true);
     }
 
     /**
@@ -236,7 +232,16 @@
      * @see <a href="https://github.com/nforge/yobi/blob/master/docs/technical/watch.md>watch.md</a>
      */
     @Transient
-    public Set<User> getWatchers(Set<User> baseWatchers) {
+    public Set<User> getWatchers(boolean allowedWatchersOnly) {
+        return getWatchers(new HashSet<User>(), allowedWatchersOnly);
+    }
+
+    /**
+     * @see {@link #getWatchers()}
+     * @see <a href="https://github.com/nforge/yobi/blob/master/docs/technical/watch.md>watch.md</a>
+     */
+    @Transient
+    public Set<User> getWatchers(Set<User> baseWatchers, boolean allowedWatchersOnly) {
         Set<User> actualWatchers = new HashSet<>();
 
         actualWatchers.addAll(baseWatchers);
@@ -249,7 +254,7 @@
             }
         }
 
-        return Watch.findActualWatchers(actualWatchers, asResource());
+        return Watch.findActualWatchers(actualWatchers, asResource(), allowedWatchersOnly);
     }
 
     protected void updateMention() {
app/models/Issue.java
--- app/models/Issue.java
+++ app/models/Issue.java
@@ -348,20 +348,25 @@
         return AbstractPosting.findByNumber(finder, project, number);
     }
 
+    @Transient
+    public Set<User> getWatchers() {
+        return getWatchers(true);
+    }
+
     /**
      * Returns all users watching or voting the issue.
      *
      * @return The set watching and voting the issue.
      */
     @Transient
-    public Set<User> getWatchers() {
+    public Set<User> getWatchers(boolean allowedWatchersOnly) {
         Set<User> baseWatchers = new HashSet<>();
         if (assignee != null) {
             baseWatchers.add(assignee.user);
         }
         baseWatchers.addAll(this.voters);
 
-        return super.getWatchers(baseWatchers);
+        return super.getWatchers(baseWatchers, allowedWatchersOnly);
     }
 
     public boolean assignedUserEquals(Assignee otherAssignee) {
app/models/PullRequest.java
--- app/models/PullRequest.java
+++ app/models/PullRequest.java
@@ -584,6 +584,10 @@
     }
 
     public Set<User> getWatchers() {
+        return getWatchers(true);
+    }
+
+    public Set<User> getWatchers(boolean allowedWatchersOnly) {
         Set<User> actualWatchers = new HashSet<>();
 
         actualWatchers.add(this.contributor);
@@ -596,7 +600,7 @@
             }
         }
 
-        return Watch.findActualWatchers(actualWatchers, asResource());
+        return Watch.findActualWatchers(actualWatchers, asResource(), allowedWatchersOnly);
     }
 
     /**
app/models/User.java
--- app/models/User.java
+++ app/models/User.java
@@ -770,21 +770,16 @@
 
     @Override
     public boolean equals(Object o) {
-        if(!(o instanceof User)) {
-            return false;
-        }
-        if(o == this) {
-            return true;
-        }
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
         User user = (User) o;
-        return this.id.equals(user.id) && this.loginId.equals(user.loginId);
+
+        return !(id != null ? !id.equals(user.id) : user.id != null);
     }
 
     @Override
     public int hashCode() {
-      int result = super.hashCode();
-      result = result * 37 + (this.id != null ? this.id.hashCode() : 0);
-      result = result * 37 + (this.loginId != null ? this.loginId.hashCode() : 0);
-      return result;
+        return id != null ? id.hashCode() : 0;
     }
 }
app/models/Watch.java
--- app/models/Watch.java
+++ app/models/Watch.java
@@ -157,7 +157,10 @@
         return isWatching(UserApp.currentUser(), resource.getType(), resource.getId());
     }
 
-    public static Set<User> findActualWatchers(final Set<User> baseWatchers, final Resource resource) {
+    public static Set<User> findActualWatchers(
+            final Set<User> baseWatchers,
+            final Resource resource,
+            boolean allowedWatchersOnly) {
         Set<User> actualWatchers = new HashSet<>();
         actualWatchers.addAll(baseWatchers);
 
@@ -172,12 +175,14 @@
         actualWatchers.removeAll(findUnwatchers(resource));
 
         // Filter the watchers who has no permission to read this resource.
-        CollectionUtils.filter(actualWatchers, new Predicate() {
-            @Override
-            public boolean evaluate(Object watcher) {
-                return AccessControl.isAllowed((User) watcher, resource, Operation.READ);
-            }
-        });
+        if (allowedWatchersOnly) {
+            CollectionUtils.filter(actualWatchers, new Predicate() {
+                @Override
+                public boolean evaluate(Object watcher) {
+                    return AccessControl.isAllowed((User) watcher, resource, Operation.READ);
+                }
+            });
+        }
         return actualWatchers;
     }
 
app/playRepository/Commit.java
--- app/playRepository/Commit.java
+++ app/playRepository/Commit.java
@@ -44,6 +44,10 @@
     public abstract int getParentCount();
 
     public Set<User> getWatchers(Project project) {
+        return getWatchers(project, true);
+    }
+
+    public Set<User> getWatchers(Project project, boolean allowedWatchersOnly) {
         Set<User> actualWatchers = new HashSet<>();
 
         // Add the author
@@ -76,7 +80,7 @@
             }
         }
 
-        return Watch.findActualWatchers(actualWatchers, asResource(project));
+        return Watch.findActualWatchers(actualWatchers, asResource(project), allowedWatchersOnly);
     }
 
     public static Project getProjectFromResourceId(String resourceId) {
app/views/board/view.scala.html
--- app/views/board/view.scala.html
+++ app/views/board/view.scala.html
@@ -72,8 +72,8 @@
     	<div class="board-footer board-actrow">
     	    <div class="pull-left">
                 @if(isAllowed(UserApp.currentUser(), post.asResource(), Operation.WATCH)){
-                    <button id="watch-button" type="button" class="ybtn @if(post.getWatchers.contains(UserApp.currentUser())){ybtn-watching}" data-toggle="button" data-watching="@if(post.getWatchers.contains(UserApp.currentUser())){true}else{false}">
-                    @if(post.getWatchers.contains(UserApp.currentUser())) { @Messages("project.unwatch") } else { @Messages("project.watch") }
+                    <button id="watch-button" type="button" class="ybtn @if(post.getWatchers(false).contains(UserApp.currentUser())){ybtn-watching}" data-toggle="button" data-watching="@if(post.getWatchers(false).contains(UserApp.currentUser())){true}else{false}">
+                    @if(post.getWatchers(false).contains(UserApp.currentUser())) { @Messages("project.unwatch") } else { @Messages("project.watch") }
                     </button>
                 }
             </div>
app/views/code/diff.scala.html
--- app/views/code/diff.scala.html
+++ app/views/code/diff.scala.html
@@ -176,7 +176,9 @@
             </div>
         </div>
 
-        <button id="watch-button" type="button" class="pull-left ybtn @if(commit.getWatchers(project).contains(UserApp.currentUser())) { active ybtn-watching }" data-toggle="button">@Messages("notification.watch")</button>
+        <button id="watch-button" type="button" class="pull-left ybtn @if(commit.getWatchers
+                (project, false).contains(UserApp.currentUser())) { active ybtn-watching }"
+        data-toggle="button">@Messages("notification.watch")</button>
 
         <a href="@routes.CodeHistoryApp.history(project.owner, project.name, selectedBranch, path)" class="ybtn pull-right">@Messages("button.list")</a>
     </div>
app/views/code/svnDiff.scala.html
--- app/views/code/svnDiff.scala.html
+++ app/views/code/svnDiff.scala.html
@@ -141,7 +141,8 @@
             @** // Comment **@
         </div>
 
-        <button id="watch-button" type="button" class="ybtn @if(commit.getWatchers(project).contains(UserApp.currentUser())) { active }" data-toggle="button">@Messages("notification.watch")</button>
+        <button id="watch-button" type="button" class="ybtn @if(commit.getWatchers(project, false)
+                .contains(UserApp.currentUser())) { active }" data-toggle="button">@Messages("notification.watch")</button>
 
         <a href="@routes.CodeHistoryApp.history(project.owner, project.name, selectedBranch, path)" class="ybtn pull-right">@Messages("button.list")</a>
 
app/views/git/view.scala.html
--- app/views/git/view.scala.html
+++ app/views/git/view.scala.html
@@ -57,8 +57,8 @@
         <div class="board-footer board-actrow">
             <div class="pull-left">
                 @if(isAllowed(UserApp.currentUser(), pull.asResource(), Operation.WATCH)) {
-                    <button id="watch-button" type="button" class="ybtn @if(pull.getWatchers.contains(UserApp.currentUser())) { ybtn-watching }" data-toggle="button" data-watching="@if(pull.getWatchers.contains(UserApp.currentUser())){true}else{false}">
-                    @if(pull.getWatchers.contains(UserApp.currentUser())) {
+                    <button id="watch-button" type="button" class="ybtn @if(pull.getWatchers(false).contains(UserApp.currentUser())) { ybtn-watching }" data-toggle="button" data-watching="@if(pull.getWatchers(false).contains(UserApp.currentUser())){true}else{false}">
+                    @if(pull.getWatchers(false).contains(UserApp.currentUser())) {
                         @Messages("project.unwatch")
                     } else {
                         @Messages("project.watch")
app/views/issue/view.scala.html
--- app/views/issue/view.scala.html
+++ app/views/issue/view.scala.html
@@ -107,9 +107,9 @@
                     <div class="pull-left">
                         <div>
                             @if(isAllowed(UserApp.currentUser(), issue.asResource(), Operation.WATCH)) {
-                                <button id="watch-button" type="button" class="ybtn @if(issue.getWatchers.contains(UserApp.currentUser())) {ybtn-watching}"
-                                        data-toggle="button" data-watching="@if(issue.getWatchers.contains(UserApp.currentUser())){true}else{false}">
-                                @if(issue.getWatchers.contains(UserApp.currentUser())) {
+                                <button id="watch-button" type="button" class="ybtn @if(issue.getWatchers(false).contains(UserApp.currentUser())) {ybtn-watching}"
+                                        data-toggle="button" data-watching="@if(issue.getWatchers(false).contains(UserApp.currentUser())){true}else{false}">
+                                @if(issue.getWatchers(false).contains(UserApp.currentUser())) {
                                     @Messages("issue.unwatch")
                                 } else {
                                     @Messages("issue.watch")
test/models/WatchTest.java
--- test/models/WatchTest.java
+++ test/models/WatchTest.java
@@ -165,7 +165,8 @@
         baseWatchers.add(base_watcher_not_member);
 
         // When
-        Set<User> actualWatchers = Watch.findActualWatchers(baseWatchers, resource_of_private_project);
+        Set<User> actualWatchers = Watch.findActualWatchers(baseWatchers,
+                resource_of_private_project, true);
 
         // Then
         assertThat(actualWatchers).containsOnly(watch_isssue, watch_project);
Add a comment
List