mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	refactor: reduce sql query in retrieveFeeds (#3547)
This commit is contained in:
		@@ -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 New Issue
	
	Block a user