Skip to content

Commit

Permalink
refactor: reduce sql query in retrieveFeeds (#3547)
Browse files Browse the repository at this point in the history
  • Loading branch information
appleboy authored Feb 21, 2018
1 parent d27d720 commit 04b3e8c
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 32 deletions.
11 changes: 10 additions & 1 deletion models/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,5 +742,14 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) {
}

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 changes: 98 additions & 0 deletions models/action_list.go
Original file line number Diff line number Diff line change
@@ -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)
}
39 changes: 8 additions & 31 deletions routers/user/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,48 +66,24 @@ func retrieveFeeds(ctx *context.Context, options models.GetFeedsOptions) {
if ctx.User != nil {
userCache[ctx.User.ID] = ctx.User
}
repoCache := map[int64]*models.Repository{}
for _, act := range actions {
// Cache results to reduce queries.
u, ok := userCache[act.ActUserID]
if !ok {
u, err = models.GetUserByID(act.ActUserID)
if err != nil {
if models.IsErrUserNotExist(err) {
continue
}
ctx.ServerError("GetUserByID", err)
return
}
userCache[act.ActUserID] = u
}
act.ActUser = u

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
}
if act.ActUser != nil {
userCache[act.ActUserID] = act.ActUser
}
act.Repo = repo

repoOwner, ok := userCache[repo.OwnerID]
repoOwner, ok := userCache[act.Repo.OwnerID]
if !ok {
repoOwner, err = models.GetUserByID(repo.OwnerID)
repoOwner, err = models.GetUserByID(act.Repo.OwnerID)
if err != nil {
if models.IsErrUserNotExist(err) {
continue
}
ctx.ServerError("GetUserByID", err)
return
}
userCache[repoOwner.ID] = repoOwner
}
repo.Owner = repoOwner
act.Repo.Owner = repoOwner
}
ctx.Data["Feeds"] = actions
}
Expand Down Expand Up @@ -154,7 +130,8 @@ func Dashboard(ctx *context.Context) {
ctx.Data["MirrorCount"] = len(mirrors)
ctx.Data["Mirrors"] = mirrors

retrieveFeeds(ctx, models.GetFeedsOptions{RequestedUser: ctxUser,
retrieveFeeds(ctx, models.GetFeedsOptions{
RequestedUser: ctxUser,
IncludePrivate: true,
OnlyPerformedBy: false,
IncludeDeleted: false,
Expand Down

0 comments on commit 04b3e8c

Please sign in to comment.