From 3c2fd7b705f29eb19baae68dd3d7e0195d00b032 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 27 Dec 2016 13:37:53 +0800 Subject: [PATCH 1/2] optimization for user.GetRepositoryAccesses to reduce db query times --- models/access.go | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/models/access.go b/models/access.go index b591e0c9db3c..e94da6c9bd24 100644 --- a/models/access.go +++ b/models/access.go @@ -4,11 +4,7 @@ package models -import ( - "fmt" - - "code.gitea.io/gitea/modules/log" -) +import "fmt" // AccessMode specifies the users access mode type AccessMode int @@ -103,26 +99,38 @@ func HasAccess(user *User, repo *Repository, testMode AccessMode) (bool, error) // GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own. func (user *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) { accesses := make([]*Access, 0, 10) - if err := x.Find(&accesses, &Access{UserID: user.ID}); err != nil { + type RepoAccess struct { + Access `xorm:"extends"` + Repository `xorm:"extends"` + } + + rows, err := x. + Join("INNER", "repository", "respository.id = access.repo_id"). + Where("access.user_id = ?", user.ID). + And("repository.owner_id <> ?", user.ID). + Rows(new(RepoAccess)) + if err != nil { return nil, err } + defer rows.Close() - repos := make(map[*Repository]AccessMode, len(accesses)) - for _, access := range accesses { - repo, err := GetRepositoryByID(access.RepoID) + var repos = make(map[*Repository]AccessMode, len(accesses)) + var ownerCache = make(map[int64]*User, len(accesses)) + for rows.Next() { + var repo RepoAccess + err = rows.Scan(&repo) if err != nil { - if IsErrRepoNotExist(err) { - log.Error(4, "GetRepositoryByID: %v", err) - continue - } return nil, err } - if err = repo.GetOwner(); err != nil { - return nil, err - } else if repo.OwnerID == user.ID { - continue + + var ok bool + if repo.Owner, ok = ownerCache[repo.OwnerID]; !ok { + if err = repo.GetOwner(); err != nil { + return nil, err + } } - repos[repo] = access.Mode + + repos[&repo.Repository] = repo.Access.Mode } return repos, nil } From 6f9d90df43960ce72d098edda8de625abfda4de0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 28 Dec 2016 09:25:34 +0800 Subject: [PATCH 2/2] fix missing cache --- models/access.go | 1 + 1 file changed, 1 insertion(+) diff --git a/models/access.go b/models/access.go index e94da6c9bd24..c77e7f0a1689 100644 --- a/models/access.go +++ b/models/access.go @@ -128,6 +128,7 @@ func (user *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) { if err = repo.GetOwner(); err != nil { return nil, err } + ownerCache[repo.OwnerID] = repo.Owner } repos[&repo.Repository] = repo.Access.Mode