Keesun Baik 2015-01-23
Reduced queries for the project's dashboard
Problem
* too mamy queries are occured when view project's dashboard.
* this can consume all db connections in a very short time.
* It took 2.5 minuetes to see the page in my local environment.

Solution
* Removed n+1 select queries.
* After this commit, it takes only 900ms to load the page.
@621b4b86857812d98c18bf3eedcb6ff808929628
app/models/Issue.java
--- app/models/Issue.java
+++ app/models/Issue.java
@@ -513,4 +513,28 @@
             return Messages.get("common.time.default.day", JodaDateUtil.localDaysBetween(now, dueDate));
         }
     }
+
+    public static int countOpenIssuesByLabel(Project project, IssueLabel label) {
+        return finder.where()
+                .eq("project", project)
+                .eq("labels", label)
+                .findRowCount();
+    }
+
+    public static int countOpenIssuesByAssignee(Project project, Assignee assignee) {
+        return finder.where()
+                .eq("project", project)
+                .eq("assignee", assignee)
+                .findRowCount();
+    }
+
+    public static int countOpenIssuesByMilestone(Project project, Milestone milestone) {
+        return finder.where()
+                .eq("project", project)
+                .eq("milestone", milestone)
+                .findRowCount();
+    }
+
+
+
 }
app/views/project/partial_dashboard_issuesbyassignee.scala.html
--- app/views/project/partial_dashboard_issuesbyassignee.scala.html
+++ app/views/project/partial_dashboard_issuesbyassignee.scala.html
@@ -29,19 +29,19 @@
         <a href="@routes.IssueApp.newIssueForm(project.owner, project.name)" target="_blank" class="ybtn ybtn-small">@Messages("issue.menu.new")</a>
     </div>
 } else {
-    @for(member <- project.members) {
-        @defining(countOpenIssuesBy(project, Map("assigneeId"->member.user.id.toString))) { assignedIssues =>
+    @for(assignee <- project.assignees) {
+        @defining(Issue.countOpenIssuesByAssignee(project, assignee)) { assignedIssues =>
             @defining(getPercent(assignedIssues, totalIssues)){ assignedPerc =>
                 @if(assignedIssues > 0){
                     <div class="row-fluid">
                         <div class="span6">
-                            <a href="@makeIssuesLink(project, scala.collection.immutable.Map("assigneeId"->member.user.id.toString))"
-                            class="usf-group" title="@member.user.name (@{"@"}@member.user.loginId)">
+                            <a href="@makeIssuesLink(project, scala.collection.immutable.Map("assigneeId"->assignee.user.id.toString))"
+                            class="usf-group" title="@assignee.user.name (@{"@"}@assignee.user.loginId)">
                                 <span class="avatar-wrap smaller">
-                                    <img src="@member.user.avatarUrl" width="20" height="20">
+                                    <img src="@assignee.user.avatarUrl" width="20" height="20">
                                 </span>
-                                <strong class="name">@member.user.name</strong>
-                                <span class="loginid"> <strong>@{"@"}</strong>@member.user.loginId</span>
+                                <strong class="name">@assignee.user.name</strong>
+                                <span class="loginid"> <strong>@{"@"}</strong>@assignee.user.loginId</span>
                             </a>
                         </div>
                         <div class="span3 num">
@@ -58,7 +58,7 @@
         }
     }
 
-    @defining(countOpenIssuesBy(project, Map("assigneeId"->User.anonymous.id.toString))) { notAssignedIssues =>
+    @defining(Issue.countOpenIssuesByAssignee(project, null)) { notAssignedIssues =>
         @defining(getPercent(notAssignedIssues, totalIssues)) { notAssignedPerc =>
             <div class="row-fluid">
                 <div class="span6">
app/views/project/partial_dashboard_issuesbylabel.scala.html
--- app/views/project/partial_dashboard_issuesbylabel.scala.html
+++ app/views/project/partial_dashboard_issuesbylabel.scala.html
@@ -40,7 +40,7 @@
                         </a>
                     </div>
                     <div class="span2 num">
-                        <strong>@countOpenIssuesBy(project, Map("labelIds"->label.id.toString))</strong>
+                        <strong>@Issue.countOpenIssuesByLabel(project, label)</strong>
                     </div>
                 </div>
             }
app/views/project/partial_dashboard_issuesbymilestone.scala.html
--- app/views/project/partial_dashboard_issuesbymilestone.scala.html
+++ app/views/project/partial_dashboard_issuesbymilestone.scala.html
@@ -31,7 +31,7 @@
         </div>
     } else {
         @for(milestone <- milestones){
-            @defining(countOpenIssuesBy(project, Map("milestoneId"->milestone.id.toString))) { milestoneIssues =>
+            @defining(Issue.countOpenIssuesByMilestone(project, milestone)) { milestoneIssues =>
                 @if(milestoneIssues > 0){
                     <div class="row-fluid">
                         <div class="span6">
@@ -52,7 +52,7 @@
             }
         }
 
-        @defining(countOpenIssuesBy(project, Map("milestoneId"->Milestone.NULL_MILESTONE_ID.toString))) { notAssignedIssues =>
+        @defining(Issue.countOpenIssuesByMilestone(project, null)) { notAssignedIssues =>
             <div class="row-fluid">
                 <div class="span6">
                     <a href="@makeIssuesLink(project, scala.collection.immutable.Map("milestoneId"->Milestone.NULL_MILESTONE_ID.toString))">
Add a comment
List