summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2022-04-01 09:53:18 +0800
committerGitHub <noreply@github.com>2022-04-01 09:53:18 +0800
commit3a73645502392110369b5d78fa2c9136e77e4aa2 (patch)
treebad6769865e3157c34540a416be455ba7c875c58 /models
parentba2592c3808bed3bdd7c7ee67cf2d9b3cef89ed2 (diff)
downloadgitea-3a73645502392110369b5d78fa2c9136e77e4aa2.tar.gz
gitea-3a73645502392110369b5d78fa2c9136e77e4aa2.zip
Performance improvement for add team user when org has more than 1000 repositories (#19227)
* performance improvement for add team user when org has more than 1000 repositories * Fix bug * Fix bug
Diffstat (limited to 'models')
-rw-r--r--models/org_team.go54
1 files changed, 42 insertions, 12 deletions
diff --git a/models/org_team.go b/models/org_team.go
index cf810cad33..695f803dbf 100644
--- a/models/org_team.go
+++ b/models/org_team.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -498,11 +499,6 @@ func AddTeamMember(team *organization.Team, userID int64) error {
}
defer committer.Close()
- // Get team and its repositories.
- if err := team.GetRepositoriesCtx(ctx); err != nil {
- return err
- }
-
sess := db.GetEngine(ctx)
if err := db.Insert(ctx, &organization.TeamUser{
@@ -518,17 +514,51 @@ func AddTeamMember(team *organization.Team, userID int64) error {
team.NumMembers++
// Give access to team repositories.
- for _, repo := range team.Repos {
- if err := recalculateUserAccess(ctx, repo, userID); err != nil {
- return err
- }
- if setting.Service.AutoWatchNewRepos {
- if err = repo_model.WatchRepoCtx(ctx, userID, repo.ID, true); err != nil {
- return err
+ // update exist access if mode become bigger
+ subQuery := builder.Select("repo_id").From("team_repo").
+ Where(builder.Eq{"team_id": team.ID})
+
+ if _, err := sess.Where("user_id=?", userID).
+ In("repo_id", subQuery).
+ And("mode < ?", team.AccessMode).
+ SetExpr("mode", team.AccessMode).
+ Update(new(Access)); err != nil {
+ return fmt.Errorf("update user accesses: %v", err)
+ }
+
+ // for not exist access
+ var repoIDs []int64
+ accessSubQuery := builder.Select("repo_id").From("access").Where(builder.Eq{"user_id": userID})
+ if err := sess.SQL(subQuery.And(builder.NotIn("repo_id", accessSubQuery))).Find(&repoIDs); err != nil {
+ return fmt.Errorf("select id accesses: %v", err)
+ }
+
+ accesses := make([]*Access, 0, 100)
+ for i, repoID := range repoIDs {
+ accesses = append(accesses, &Access{RepoID: repoID, UserID: userID, Mode: team.AccessMode})
+ if (i%100 == 0 || i == len(repoIDs)-1) && len(accesses) > 0 {
+ if err = db.Insert(ctx, accesses); err != nil {
+ return fmt.Errorf("insert new user accesses: %v", err)
}
+ accesses = accesses[:0]
}
}
+ // watch could be failed, so run it in a goroutine
+ if setting.Service.AutoWatchNewRepos {
+ // Get team and its repositories.
+ if err := team.GetRepositoriesCtx(db.DefaultContext); err != nil {
+ log.Error("getRepositories failed: %v", err)
+ }
+ go func(repos []*repo_model.Repository) {
+ for _, repo := range repos {
+ if err = repo_model.WatchRepoCtx(db.DefaultContext, userID, repo.ID, true); err != nil {
+ log.Error("watch repo failed: %v", err)
+ }
+ }
+ }(team.Repos)
+ }
+
return committer.Commit()
}