mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 10:18:38 +00:00
Add a new table issue_index to store the max issue index so that issue could be deleted with no duplicated index (#15599)
* Add a new table issue_index to store the max issue index so that issue could be deleted with no duplicated index * Fix pull index * Add tests for concurrent creating issues * Fix lint * Fix tests * Fix postgres test * Add test for migration v180 * Rename wrong test file name Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
@@ -78,9 +78,8 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
issueTasksRegexpStr = `(^\s*[-*]\s\[[\sxX]\]\s.)|(\n\s*[-*]\s\[[\sxX]\]\s.)`
|
||||
issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[xX]\]\s.)|(\n\s*[-*]\s\[[xX]\]\s.)`
|
||||
issueMaxDupIndexAttempts = 3
|
||||
issueTasksRegexpStr = `(^\s*[-*]\s\[[\sxX]\]\s.)|(\n\s*[-*]\s\[[\sxX]\]\s.)`
|
||||
issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[xX]\]\s.)|(\n\s*[-*]\s\[[xX]\]\s.)`
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -896,21 +895,17 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Milestone validation should happen before insert actual object.
|
||||
if _, err := e.SetExpr("`index`", "coalesce(MAX(`index`),0)+1").
|
||||
Where("repo_id=?", opts.Issue.RepoID).
|
||||
Insert(opts.Issue); err != nil {
|
||||
return ErrNewIssueInsert{err}
|
||||
if opts.Issue.Index <= 0 {
|
||||
return fmt.Errorf("no issue index provided")
|
||||
}
|
||||
if opts.Issue.ID > 0 {
|
||||
return fmt.Errorf("issue exist")
|
||||
}
|
||||
|
||||
inserted, err := getIssueByID(e, opts.Issue.ID)
|
||||
if err != nil {
|
||||
if _, err := e.Insert(opts.Issue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch Index with the value calculated by the database
|
||||
opts.Issue.Index = inserted.Index
|
||||
|
||||
if opts.Issue.MilestoneID > 0 {
|
||||
if _, err = e.Exec("UPDATE `milestone` SET num_issues=num_issues+1 WHERE id=?", opts.Issue.MilestoneID); err != nil {
|
||||
return err
|
||||
@@ -987,24 +982,13 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
||||
|
||||
// NewIssue creates new issue with labels for repository.
|
||||
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
||||
// Retry several times in case INSERT fails due to duplicate key for (repo_id, index); see #7887
|
||||
i := 0
|
||||
for {
|
||||
if err = newIssueAttempt(repo, issue, labelIDs, uuids); err == nil {
|
||||
return nil
|
||||
}
|
||||
if !IsErrNewIssueInsert(err) {
|
||||
return err
|
||||
}
|
||||
if i++; i == issueMaxDupIndexAttempts {
|
||||
break
|
||||
}
|
||||
log.Error("NewIssue: error attempting to insert the new issue; will retry. Original error: %v", err)
|
||||
idx, err := GetNextResourceIndex("issue_index", repo.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generate issue index failed: %v", err)
|
||||
}
|
||||
return fmt.Errorf("NewIssue: too many errors attempting to insert the new issue. Last error was: %v", err)
|
||||
}
|
||||
|
||||
func newIssueAttempt(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
||||
issue.Index = idx
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
|
Reference in New Issue
Block a user