Keep database transactions not too big (#13254)

* Keep database transactions not too big

* Fix #13255

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Only cache the last repo

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
Lunny Xiao 2020-10-22 23:45:54 +08:00 committed by GitHub
parent e964c6ec18
commit be82b8f99a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -10,6 +10,7 @@ import (
"strings" "strings"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"xorm.io/xorm" "xorm.io/xorm"
@ -37,6 +38,7 @@ func fixPublisherIDforTagReleases(x *xorm.Engine) error {
type Repository struct { type Repository struct {
ID int64 ID int64
OwnerID int64 OwnerID int64
OwnerName string
Name string Name string
} }
@ -50,27 +52,23 @@ func fixPublisherIDforTagReleases(x *xorm.Engine) error {
sess := x.NewSession() sess := x.NewSession()
defer sess.Close() defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
var ( var (
gitRepoCache = make(map[int64]*git.Repository) repo *Repository
gitRepo *git.Repository gitRepo *git.Repository
repoCache = make(map[int64]*Repository)
userCache = make(map[int64]*User)
ok bool
err error
) )
defer func() { defer func() {
for i := range gitRepoCache { if gitRepo != nil {
gitRepoCache[i].Close() gitRepo.Close()
} }
}() }()
for start := 0; ; start += batchSize { for start := 0; ; start += batchSize {
releases := make([]*Release, 0, batchSize) releases := make([]*Release, 0, batchSize)
if err := sess.Limit(batchSize, start).Asc("id").Where("is_tag=?", true).Find(&releases); err != nil { if err := sess.Begin(); err != nil {
return err
}
if err := sess.Limit(batchSize, start).Asc("repo_id", "id").Where("is_tag=?", true).Find(&releases); err != nil {
return err return err
} }
@ -79,39 +77,36 @@ func fixPublisherIDforTagReleases(x *xorm.Engine) error {
} }
for _, release := range releases { for _, release := range releases {
gitRepo, ok = gitRepoCache[release.RepoID] if repo == nil || repo.ID != release.RepoID {
if !ok { if gitRepo != nil {
repo, ok := repoCache[release.RepoID] gitRepo.Close()
if !ok { gitRepo = nil
}
repo = new(Repository) repo = new(Repository)
has, err := sess.ID(release.RepoID).Get(repo) has, err := sess.ID(release.RepoID).Get(repo)
if err != nil { if err != nil {
return err return err
} else if !has { } else if !has {
return fmt.Errorf("Repository %d is not exist", release.RepoID) log.Warn("Release[%d] is orphaned and refers to non-existing repository %d", release.ID, release.RepoID)
log.Warn("This release should be deleted")
continue
} }
repoCache[release.RepoID] = repo if repo.OwnerName == "" {
} // v120.go migration may not have been run correctly - we'll just replicate it here
// because this appears to be a common-ish problem.
user, ok := userCache[repo.OwnerID] if _, err := sess.Exec("UPDATE repository SET owner_name = (SELECT name FROM `user` WHERE `user`.id = repository.owner_id)"); err != nil {
if !ok {
user = new(User)
has, err := sess.ID(repo.OwnerID).Get(user)
if err != nil {
return err return err
} else if !has {
return fmt.Errorf("User %d is not exist", repo.OwnerID)
} }
userCache[repo.OwnerID] = user if _, err := sess.ID(release.RepoID).Get(repo); err != nil {
return err
} }
}
gitRepo, err = git.OpenRepository(repoPath(user.Name, repo.Name)) gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name))
if err != nil { if err != nil {
return err return err
} }
gitRepoCache[release.RepoID] = gitRepo
} }
commit, err := gitRepo.GetTagCommit(release.TagName) commit, err := gitRepo.GetTagCommit(release.TagName)
@ -134,7 +129,11 @@ func fixPublisherIDforTagReleases(x *xorm.Engine) error {
return err return err
} }
} }
if err := sess.Commit(); err != nil {
return err
}
} }
return sess.Commit() return nil
} }