use GetLatestCommitStatuses instead GetLatestCommitStatus to reduce db operations

This commit is contained in:
Lunny Xiao 2017-09-17 12:37:24 +08:00
parent 7f886eccd0
commit 21b57b6bc5
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
5 changed files with 102 additions and 15 deletions

View File

@ -6,6 +6,7 @@ package models
import (
"container/list"
"errors"
"fmt"
"strings"
@ -15,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/util"
api "code.gitea.io/sdk/gitea"
"github.com/go-xorm/builder"
"github.com/go-xorm/xorm"
)
@ -157,6 +159,59 @@ func GetLatestCommitStatus(repo *Repository, sha string, page int) ([]*CommitSta
return statuses, x.In("id", ids).Find(&statuses)
}
// GetLatestCommitStatuses returns all statuses with given repoIDs and shas
func GetLatestCommitStatuses(repoIDs []int64, shas []string) ([][]*CommitStatus, error) {
if len(repoIDs) != len(shas) {
return nil, errors.New("parameter repoIDs should have the same size of shas")
}
var results = make([]struct {
ID int64
RepoID int64
}, 0, 10*len(repoIDs))
var cond = builder.NewCond()
for i := 0; i < len(repoIDs); i++ {
cond = cond.Or(builder.Eq{
"repo_id": repoIDs[i],
"sha": shas[i],
})
}
err := x.Table(&CommitStatus{}).
Where(cond).
Select("max( id ) as id, repo_id").
GroupBy("context").OrderBy("max( id ) desc").Find(&results)
if err != nil {
return nil, err
}
var returns = make([][]*CommitStatus, len(repoIDs))
if len(results) == 0 {
return returns, nil
}
var ids = make([]int64, 0, len(results))
var repoIDsMap = make(map[int64][]int64, len(repoIDs))
for _, res := range results {
ids = append(ids, res.ID)
repoIDsMap[res.RepoID] = append(repoIDsMap[res.RepoID], res.ID)
}
statuses := make(map[int64]*CommitStatus, len(ids))
err = x.In("id", ids).Find(&statuses)
if err != nil {
return nil, err
}
for i := 0; i < len(repoIDs); i++ {
for _, id := range repoIDsMap[repoIDs[i]] {
returns[i] = append(returns[i], statuses[id])
}
}
return returns, nil
}
// GetCommitStatus populates a given status for a given commit.
// NOTE: If ID or Index isn't given, and only Context, TargetURL and/or Description
// is given, the CommitStatus created _last_ will be returned.

View File

@ -209,7 +209,9 @@ func Issues(ctx *context.Context) {
}
}
var issuesStates = make([]*models.CommitStatus, 0, len(issues))
var repoIDs = make([]int64, 0, len(issues))
var shas = make([]string, 0, len(issues))
var pullIDs = make([]int64, 0, len(issues))
// Get posters.
for i, issue := range issues {
// Check read status
@ -221,15 +223,28 @@ func Issues(ctx *context.Context) {
}
if issue.IsPull {
issue.LoadAttributes()
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository, issue.PullRequest.MergeBase, 0)
if err != nil {
log.Error(3, "GetLatestCommitStatus: %v", err)
if err := issue.LoadAttributes(); err != nil {
ctx.ServerError("LoadAttributes", err)
return
}
issuesStates = append(issuesStates, models.CalcCommitStatus(statuses))
repoIDs = append(repoIDs, ctx.Repo.Repository.ID)
shas = append(shas, issue.PullRequest.MergeBase)
pullIDs = append(pullIDs, issue.ID)
}
}
commitStatuses, err := models.GetLatestCommitStatuses(repoIDs, shas)
if err != nil {
ctx.ServerError("GetLatestCommitStatuses", err)
return
}
var issuesStates = make(map[int64]*models.CommitStatus, len(issues))
for i, statuses := range commitStatuses {
issuesStates[pullIDs[i]] = models.CalcCommitStatus(statuses)
}
ctx.Data["Issues"] = issues
ctx.Data["IssuesStates"] = issuesStates

View File

@ -12,7 +12,6 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@ -292,21 +291,37 @@ func Issues(ctx *context.Context) {
return
}
var issuesStates = make([]*models.CommitStatus, 0, len(issues))
var repoIDs = make([]int64, 0, len(issues))
var shas = make([]string, 0, len(issues))
var pullIDs = make([]int64, 0, len(issues))
for _, issue := range issues {
issue.Repo = showReposMap[issue.RepoID]
if issue.IsPull {
issue.LoadAttributes()
statuses, err := models.GetLatestCommitStatus(issue.Repo, issue.PullRequest.MergeBase, 0)
if err != nil {
log.Error(3, "GetLatestCommitStatus: %v", err)
if err := issue.LoadAttributes(); err != nil {
ctx.ServerError("LoadAttributes", fmt.Errorf("%v", err))
return
}
issuesStates = append(issuesStates, models.CalcCommitStatus(statuses))
repoIDs = append(repoIDs, issue.Repo.ID)
shas = append(shas, issue.PullRequest.MergeBase)
pullIDs = append(pullIDs, issue.ID)
}
}
commitStatuses, err := models.GetLatestCommitStatuses(repoIDs, shas)
if err != nil {
ctx.ServerError("GetLatestCommitStatuses", err)
return
}
var issuesStates = make(map[int64]*models.CommitStatus, len(issues))
for i, statuses := range commitStatuses {
issuesStates[pullIDs[i]] = models.CalcCommitStatus(statuses)
}
ctx.Data["IssuesStates"] = issuesStates
issueStats, err := models.GetUserIssueStats(models.UserIssueStatsOptions{
UserID: ctxUser.ID,
RepoID: repoID,

View File

@ -187,7 +187,7 @@
<div class="ui {{if $issue.IsRead}}black{{else}}green{{end}} label">#{{$issue.Index}}</div>
<a class="title has-emoji" href="{{$.Link}}/{{$issue.Index}}">{{$issue.Title}}</a>
{{if $issue.IsPull}}
{{template "repo/commit_status" (index $.IssuesStates $index)}}
{{template "repo/commit_status" (index $.IssuesStates $issue.ID)}}
{{end}}
{{if $issue.Ref}}
<a class="ui label" href="{{$.RepoLink}}/src/branch/{{$issue.Ref}}">{{$issue.Ref}}</a>

View File

@ -63,7 +63,9 @@
<li class="item">
<div class="ui label">{{if not $.RepoID}}{{$issue.Repo.FullName}}{{end}}#{{$issue.Index}}</div>
<a class="title has-emoji" href="{{AppSubUrl}}/{{$issue.Repo.Owner.Name}}/{{$issue.Repo.Name}}/issues/{{$issue.Index}}">{{$issue.Title}}</a>
{{if $issue.IsPull}}
{{template "repo/commit_status" (index $.IssuesStates $issue.ID)}}
{{end}}
{{with $issue.Labels}}
{{/* If we have any labels, we should show them
with a 2.5 line height, this way they don't look