Skip to content

Commit

Permalink
Performance improvement for add team user when org has more than 1000…
Browse files Browse the repository at this point in the history
… repositories (go-gitea#19227)

* performance improvement for add team user when org has more than 1000 repositories

* Fix bug

* Fix bug
  • Loading branch information
lunny committed Apr 1, 2022
1 parent 123c254 commit cc14959
Showing 1 changed file with 41 additions and 12 deletions.
53 changes: 41 additions & 12 deletions models/org_team.go
Original file line number Diff line number Diff line change
Expand Up @@ -940,11 +940,6 @@ func AddTeamMember(team *Team, userID int64) error {
return err
}

// Get team and its repositories.
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
return err
}

ctx, committer, err := db.TxContext()
if err != nil {
return err
Expand All @@ -966,17 +961,51 @@ func AddTeamMember(team *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.GetRepositories(&SearchOrgTeamOptions{}); 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()
}

Expand Down

0 comments on commit cc14959

Please sign in to comment.