aboutsummaryrefslogtreecommitdiffstats
path: root/models/issue.go
diff options
context:
space:
mode:
authorguillep2k <18600385+guillep2k@users.noreply.github.com>2019-08-26 23:17:23 -0300
committertechknowlogick <techknowlogick@gitea.io>2019-08-26 22:17:23 -0400
commit5fe2ec264febd6a4112c5f8c72c170f016bdf0c8 (patch)
treebc1261858b8278189d7b30c51faaa9b442245d0d /models/issue.go
parent541fab196f216771a51419a8b8d353694afa6c45 (diff)
downloadgitea-5fe2ec264febd6a4112c5f8c72c170f016bdf0c8.tar.gz
gitea-5fe2ec264febd6a4112c5f8c72c170f016bdf0c8.zip
Retry create issue to cope with duplicate keys (#7898)
* Retry create issue to cope with duplicate keys * Use .SetExpr().Where().Insert()
Diffstat (limited to 'models/issue.go')
-rw-r--r--models/issue.go52
1 files changed, 23 insertions, 29 deletions
diff --git a/models/issue.go b/models/issue.go
index fc74c73162..b849f97bd4 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -5,7 +5,6 @@
package models
import (
- "errors"
"fmt"
"path"
"regexp"
@@ -74,6 +73,7 @@ var (
const issueTasksRegexpStr = `(^\s*[-*]\s\[[\sx]\]\s.)|(\n\s*[-*]\s\[[\sx]\]\s.)`
const issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[x]\]\s.)|(\n\s*[-*]\s\[[x]\]\s.)`
+const issueMaxDupIndexAttempts = 3
func init() {
issueTasksPat = regexp.MustCompile(issueTasksRegexpStr)
@@ -1031,36 +1031,9 @@ type NewIssueOptions struct {
IsPull bool
}
-// GetMaxIndexOfIssue returns the max index on issue
-func GetMaxIndexOfIssue(repoID int64) (int64, error) {
- return getMaxIndexOfIssue(x, repoID)
-}
-
-func getMaxIndexOfIssue(e Engine, repoID int64) (int64, error) {
- var (
- maxIndex int64
- has bool
- err error
- )
-
- has, err = e.SQL("SELECT COALESCE((SELECT MAX(`index`) FROM issue WHERE repo_id = ?),0)", repoID).Get(&maxIndex)
- if err != nil {
- return 0, err
- } else if !has {
- return 0, errors.New("Retrieve Max index from issue failed")
- }
- return maxIndex, nil
-}
-
func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
opts.Issue.Title = strings.TrimSpace(opts.Issue.Title)
- maxIndex, err := getMaxIndexOfIssue(e, opts.Issue.RepoID)
- if err != nil {
- return err
- }
- opts.Issue.Index = maxIndex + 1
-
if opts.Issue.MilestoneID > 0 {
milestone, err := getMilestoneByRepoID(e, opts.Issue.RepoID, opts.Issue.MilestoneID)
if err != nil && !IsErrMilestoneNotExist(err) {
@@ -1109,10 +1082,31 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
}
// Milestone and assignee validation should happen before insert actual object.
- if _, err = e.Insert(opts.Issue); err != nil {
+
+ // There's no good way to identify a duplicate key error in database/sql; brute force some retries
+ dupIndexAttempts := issueMaxDupIndexAttempts
+ for {
+ _, err := e.SetExpr("`index`", "coalesce(MAX(`index`),0)+1").
+ Where("repo_id=?", opts.Issue.RepoID).
+ Insert(opts.Issue)
+ if err == nil {
+ break
+ }
+
+ dupIndexAttempts--
+ if dupIndexAttempts <= 0 {
+ return err
+ }
+ }
+
+ inserted, err := getIssueByID(e, opts.Issue.ID)
+ if 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 = changeMilestoneAssign(e, doer, opts.Issue, -1); err != nil {
return err