Skip to content

Commit 471a1e8

Browse files
authored
Performance improvement for add team user when org has more than 1000 repositories (#19227) (#19289)
1 parent 123c254 commit 471a1e8

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

models/org_team.go

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -940,11 +940,6 @@ func AddTeamMember(team *Team, userID int64) error {
940940
return err
941941
}
942942

943-
// Get team and its repositories.
944-
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
945-
return err
946-
}
947-
948943
ctx, committer, err := db.TxContext()
949944
if err != nil {
950945
return err
@@ -966,17 +961,51 @@ func AddTeamMember(team *Team, userID int64) error {
966961
team.NumMembers++
967962

968963
// Give access to team repositories.
969-
for _, repo := range team.Repos {
970-
if err := recalculateUserAccess(ctx, repo, userID); err != nil {
971-
return err
972-
}
973-
if setting.Service.AutoWatchNewRepos {
974-
if err = repo_model.WatchRepoCtx(ctx, userID, repo.ID, true); err != nil {
975-
return err
964+
// update exist access if mode become bigger
965+
subQuery := builder.Select("repo_id").From("team_repo").
966+
Where(builder.Eq{"team_id": team.ID})
967+
968+
if _, err := sess.Where("user_id=?", userID).
969+
In("repo_id", subQuery).
970+
And("mode < ?", team.AccessMode).
971+
SetExpr("mode", team.AccessMode).
972+
Update(new(Access)); err != nil {
973+
return fmt.Errorf("update user accesses: %v", err)
974+
}
975+
976+
// for not exist access
977+
var repoIDs []int64
978+
accessSubQuery := builder.Select("repo_id").From("access").Where(builder.Eq{"user_id": userID})
979+
if err := sess.SQL(subQuery.And(builder.NotIn("repo_id", accessSubQuery))).Find(&repoIDs); err != nil {
980+
return fmt.Errorf("select id accesses: %v", err)
981+
}
982+
983+
accesses := make([]*Access, 0, 100)
984+
for i, repoID := range repoIDs {
985+
accesses = append(accesses, &Access{RepoID: repoID, UserID: userID, Mode: team.AccessMode})
986+
if (i%100 == 0 || i == len(repoIDs)-1) && len(accesses) > 0 {
987+
if err = db.Insert(ctx, accesses); err != nil {
988+
return fmt.Errorf("insert new user accesses: %v", err)
976989
}
990+
accesses = accesses[:0]
977991
}
978992
}
979993

994+
// watch could be failed, so run it in a goroutine
995+
if setting.Service.AutoWatchNewRepos {
996+
// Get team and its repositories.
997+
if err := team.GetRepositories(&SearchOrgTeamOptions{}); err != nil {
998+
log.Error("getRepositories failed: %v", err)
999+
}
1000+
go func(repos []*repo_model.Repository) {
1001+
for _, repo := range repos {
1002+
if err = repo_model.WatchRepoCtx(db.DefaultContext, userID, repo.ID, true); err != nil {
1003+
log.Error("watch repo failed: %v", err)
1004+
}
1005+
}
1006+
}(team.Repos)
1007+
}
1008+
9801009
return committer.Commit()
9811010
}
9821011

0 commit comments

Comments
 (0)