Skip to content

Commit 01cacce

Browse files
committed
performance improvement for add team user when org has more than 1000 repositories
1 parent ba2592c commit 01cacce

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

models/org_team.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"code.gitea.io/gitea/models/organization"
1616
repo_model "code.gitea.io/gitea/models/repo"
1717
user_model "code.gitea.io/gitea/models/user"
18+
"code.gitea.io/gitea/modules/log"
1819
"code.gitea.io/gitea/modules/setting"
1920
"code.gitea.io/gitea/modules/util"
2021

@@ -488,18 +489,13 @@ func AddTeamMember(team *organization.Team, userID int64) error {
488489
return err
489490
}
490491

491-
if err := organization.AddOrgUser(team.OrgID, userID); err != nil {
492-
return err
493-
}
494-
495492
ctx, committer, err := db.TxContext()
496493
if err != nil {
497494
return err
498495
}
499496
defer committer.Close()
500497

501-
// Get team and its repositories.
502-
if err := team.GetRepositoriesCtx(ctx); err != nil {
498+
if err := AddOrgUser(ctx, team.OrgID, userID); err != nil {
503499
return err
504500
}
505501

@@ -518,17 +514,50 @@ func AddTeamMember(team *organization.Team, userID int64) error {
518514
team.NumMembers++
519515

520516
// Give access to team repositories.
521-
for _, repo := range team.Repos {
522-
if err := recalculateUserAccess(ctx, repo, userID); err != nil {
523-
return err
524-
}
525-
if setting.Service.AutoWatchNewRepos {
526-
if err = repo_model.WatchRepoCtx(ctx, userID, repo.ID, true); err != nil {
527-
return err
517+
// update exist access if mode become bigger
518+
subQuery := builder.Select("repo_id").From("team_repo").
519+
Where(builder.Eq{"team_id": team.ID})
520+
521+
if _, err := sess.Where("user_id=?", userID).
522+
In("repo_id", subQuery).
523+
And("mode < ?", team.AccessMode).
524+
SetExpr("mode", team.AccessMode).
525+
Update(new(Access)); err != nil {
526+
return fmt.Errorf("update user accesses: %v", err)
527+
}
528+
529+
// for not exist access
530+
var repoIDs []int64
531+
accessSubQuery := builder.Select("repo_id").From("access").Where(builder.Eq{"user_id": userID})
532+
if err := sess.SQL(subQuery.And(builder.NotIn("repo_id", accessSubQuery))).Find(&repoIDs); err != nil {
533+
return fmt.Errorf("select id accesses: %v", err)
534+
}
535+
536+
accesses := make([]*Access, 0, 100)
537+
for i, repoID := range repoIDs {
538+
accesses = append(accesses, &Access{RepoID: repoID, UserID: userID})
539+
if (i%100 == 0 || i == len(repoIDs)-1) && len(accesses) > 0 {
540+
if err = db.Insert(ctx, accesses); err != nil {
541+
return fmt.Errorf("insert new user accesses: %v", err)
528542
}
543+
accesses = accesses[:0]
529544
}
530545
}
531546

547+
// watch could be failed, so run it in a goroutine
548+
if setting.Service.AutoWatchNewRepos {
549+
if err := team.getRepositories(db.GetEngine(db.DefaultContext)); err != nil {
550+
log.Error("getRepositories failed: %v", err)
551+
}
552+
go func(repos []*repo_model.Repository) {
553+
for _, repo := range repos {
554+
if err = repo_model.WatchRepoCtx(db.DefaultContext, userID, repo.ID, true); err != nil {
555+
log.Error("watch repo failed: %v", err)
556+
}
557+
}
558+
}(team.Repos)
559+
}
560+
532561
return committer.Commit()
533562
}
534563

models/repo_transfer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ func TransferOwnership(doer *user_model.User, newOwnerName string, repo *repo_mo
297297
}
298298

299299
if c.ID != newOwner.ID {
300-
isMember, err := organization.IsOrganizationMember(ctx, newOwner.ID, c.ID)
300+
isMember, err := organization.IsOrganizationMember(ctx, newOwner.ID, c.ID)000 repositories)
301301
if err != nil {
302302
return fmt.Errorf("IsOrgMember: %v", err)
303303
} else if !isMember {

0 commit comments

Comments
 (0)