refactor: reduce sql query in retrieveFeeds (#3547)
This commit is contained in:
parent
d27d720f05
commit
04b3e8cbdc
3 changed files with 118 additions and 34 deletions
|
@ -742,5 +742,14 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
actions := make([]*Action, 0, 20)
|
actions := make([]*Action, 0, 20)
|
||||||
return actions, x.Limit(20).Desc("id").Where(cond).Find(&actions)
|
|
||||||
|
if err := x.Limit(20).Desc("id").Where(cond).Find(&actions); err != nil {
|
||||||
|
return nil, fmt.Errorf("Find: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ActionList(actions).LoadAttributes(); err != nil {
|
||||||
|
return nil, fmt.Errorf("LoadAttributes: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions, nil
|
||||||
}
|
}
|
||||||
|
|
98
models/action_list.go
Normal file
98
models/action_list.go
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// ActionList defines a list of actions
|
||||||
|
type ActionList []*Action
|
||||||
|
|
||||||
|
func (actions ActionList) getUserIDs() []int64 {
|
||||||
|
userIDs := make(map[int64]struct{}, len(actions))
|
||||||
|
for _, action := range actions {
|
||||||
|
if _, ok := userIDs[action.ActUserID]; !ok {
|
||||||
|
userIDs[action.ActUserID] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keysInt64(userIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (actions ActionList) loadUsers(e Engine) ([]*User, error) {
|
||||||
|
if len(actions) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
userIDs := actions.getUserIDs()
|
||||||
|
userMaps := make(map[int64]*User, len(userIDs))
|
||||||
|
err := e.
|
||||||
|
In("id", userIDs).
|
||||||
|
Find(&userMaps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, action := range actions {
|
||||||
|
action.ActUser = userMaps[action.ActUserID]
|
||||||
|
}
|
||||||
|
return valuesUser(userMaps), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadUsers loads actions' all users
|
||||||
|
func (actions ActionList) LoadUsers() ([]*User, error) {
|
||||||
|
return actions.loadUsers(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (actions ActionList) getRepoIDs() []int64 {
|
||||||
|
repoIDs := make(map[int64]struct{}, len(actions))
|
||||||
|
for _, action := range actions {
|
||||||
|
if _, ok := repoIDs[action.RepoID]; !ok {
|
||||||
|
repoIDs[action.RepoID] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keysInt64(repoIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (actions ActionList) loadRepositories(e Engine) ([]*Repository, error) {
|
||||||
|
if len(actions) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
repoIDs := actions.getRepoIDs()
|
||||||
|
repoMaps := make(map[int64]*Repository, len(repoIDs))
|
||||||
|
err := e.
|
||||||
|
In("id", repoIDs).
|
||||||
|
Find(&repoMaps)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("find repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, action := range actions {
|
||||||
|
action.Repo = repoMaps[action.RepoID]
|
||||||
|
}
|
||||||
|
return valuesRepository(repoMaps), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadRepositories loads actions' all repositories
|
||||||
|
func (actions ActionList) LoadRepositories() ([]*Repository, error) {
|
||||||
|
return actions.loadRepositories(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadAttributes loads all attributes
|
||||||
|
func (actions ActionList) loadAttributes(e Engine) (err error) {
|
||||||
|
if _, err = actions.loadUsers(e); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = actions.loadRepositories(e); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAttributes loads attributes of the actions
|
||||||
|
func (actions ActionList) LoadAttributes() error {
|
||||||
|
return actions.loadAttributes(x)
|
||||||
|
}
|
|
@ -66,12 +66,14 @@ func retrieveFeeds(ctx *context.Context, options models.GetFeedsOptions) {
|
||||||
if ctx.User != nil {
|
if ctx.User != nil {
|
||||||
userCache[ctx.User.ID] = ctx.User
|
userCache[ctx.User.ID] = ctx.User
|
||||||
}
|
}
|
||||||
repoCache := map[int64]*models.Repository{}
|
|
||||||
for _, act := range actions {
|
for _, act := range actions {
|
||||||
// Cache results to reduce queries.
|
if act.ActUser != nil {
|
||||||
u, ok := userCache[act.ActUserID]
|
userCache[act.ActUserID] = act.ActUser
|
||||||
|
}
|
||||||
|
|
||||||
|
repoOwner, ok := userCache[act.Repo.OwnerID]
|
||||||
if !ok {
|
if !ok {
|
||||||
u, err = models.GetUserByID(act.ActUserID)
|
repoOwner, err = models.GetUserByID(act.Repo.OwnerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrUserNotExist(err) {
|
if models.IsErrUserNotExist(err) {
|
||||||
continue
|
continue
|
||||||
|
@ -79,35 +81,9 @@ func retrieveFeeds(ctx *context.Context, options models.GetFeedsOptions) {
|
||||||
ctx.ServerError("GetUserByID", err)
|
ctx.ServerError("GetUserByID", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userCache[act.ActUserID] = u
|
userCache[repoOwner.ID] = repoOwner
|
||||||
}
|
}
|
||||||
act.ActUser = u
|
act.Repo.Owner = repoOwner
|
||||||
|
|
||||||
repo, ok := repoCache[act.RepoID]
|
|
||||||
if !ok {
|
|
||||||
repo, err = models.GetRepositoryByID(act.RepoID)
|
|
||||||
if err != nil {
|
|
||||||
if models.IsErrRepoNotExist(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ctx.ServerError("GetRepositoryByID", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
act.Repo = repo
|
|
||||||
|
|
||||||
repoOwner, ok := userCache[repo.OwnerID]
|
|
||||||
if !ok {
|
|
||||||
repoOwner, err = models.GetUserByID(repo.OwnerID)
|
|
||||||
if err != nil {
|
|
||||||
if models.IsErrUserNotExist(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ctx.ServerError("GetUserByID", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repo.Owner = repoOwner
|
|
||||||
}
|
}
|
||||||
ctx.Data["Feeds"] = actions
|
ctx.Data["Feeds"] = actions
|
||||||
}
|
}
|
||||||
|
@ -154,7 +130,8 @@ func Dashboard(ctx *context.Context) {
|
||||||
ctx.Data["MirrorCount"] = len(mirrors)
|
ctx.Data["MirrorCount"] = len(mirrors)
|
||||||
ctx.Data["Mirrors"] = mirrors
|
ctx.Data["Mirrors"] = mirrors
|
||||||
|
|
||||||
retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
|
retrieveFeeds(ctx, models.GetFeedsOptions{
|
||||||
|
RequestedUser: ctxUser,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
OnlyPerformedBy: false,
|
OnlyPerformedBy: false,
|
||||||
IncludeDeleted: false,
|
IncludeDeleted: false,
|
||||||
|
|
Reference in a new issue