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
This commit is contained in:
parent
ba2592c380
commit
3a73645502
1 changed files with 42 additions and 12 deletions
|
@ -15,6 +15,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
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/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
@ -498,11 +499,6 @@ func AddTeamMember(team *organization.Team, userID int64) error {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
// Get team and its repositories.
|
|
||||||
if err := team.GetRepositoriesCtx(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if err := db.Insert(ctx, &organization.TeamUser{
|
if err := db.Insert(ctx, &organization.TeamUser{
|
||||||
|
@ -518,15 +514,49 @@ func AddTeamMember(team *organization.Team, userID int64) error {
|
||||||
team.NumMembers++
|
team.NumMembers++
|
||||||
|
|
||||||
// Give access to team repositories.
|
// Give access to team repositories.
|
||||||
for _, repo := range team.Repos {
|
// update exist access if mode become bigger
|
||||||
if err := recalculateUserAccess(ctx, repo, userID); err != nil {
|
subQuery := builder.Select("repo_id").From("team_repo").
|
||||||
return err
|
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 {
|
if setting.Service.AutoWatchNewRepos {
|
||||||
if err = repo_model.WatchRepoCtx(ctx, userID, repo.ID, true); err != nil {
|
// Get team and its repositories.
|
||||||
return err
|
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()
|
return committer.Commit()
|
||||||
|
|
Reference in a new issue