From 066d8a55907534ab1a05258a752e98cef50562c7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 6 May 2023 21:54:02 +0800 Subject: [PATCH 01/12] Add more context on log for generating parall commit status index --- models/git/commit_status.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 82cbb2363739f..51f76af294d5d 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -74,7 +74,7 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in // try to update the max_index to next value, and acquire the write-lock for the record res, err := e.Exec("UPDATE `commit_status_index` SET max_index=max_index+1 WHERE repo_id=? AND sha=?", repoID, sha) if err != nil { - return 0, err + return 0, fmt.Errorf("update failed: %w", err) } affected, err := res.RowsAffected() if err != nil { @@ -85,18 +85,18 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in _, errIns := e.Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) VALUES (?, ?, 0)", repoID, sha) res, err = e.Exec("UPDATE `commit_status_index` SET max_index=max_index+1 WHERE repo_id=? AND sha=?", repoID, sha) if err != nil { - return 0, err + return 0, fmt.Errorf("update2 failed: %w", err) } affected, err = res.RowsAffected() if err != nil { - return 0, err + return 0, fmt.Errorf("RowsAffected failed: %w", err) } // if the update still can not update any records, the record must not exist and there must be some errors (insert error) if affected == 0 { if errIns == nil { return 0, errors.New("impossible error when GetNextCommitStatusIndex, insert and update both succeeded but no record is updated") } - return 0, errIns + return 0, fmt.Errorf("insert failed: %w", errIns) } } @@ -104,7 +104,7 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in var newIdx int64 has, err := e.SQL("SELECT max_index FROM `commit_status_index` WHERE repo_id=? AND sha=?", repoID, sha).Get(&newIdx) if err != nil { - return 0, err + return 0, fmt.Errorf("select failed: %w", err) } if !has { return 0, errors.New("impossible error when GetNextCommitStatusIndex, upsert succeeded but no record can be selected") From 965f2cffcc6ba74a6db8ed07f1313915f38a4300 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 8 May 2023 18:50:47 +0800 Subject: [PATCH 02/12] Fix commit status insert --- models/git/commit_status.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 51f76af294d5d..98174dfd42fa5 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -82,7 +82,24 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in } if affected == 0 { // this slow path is only for the first time of creating a resource index - _, errIns := e.Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) VALUES (?, ?, 0)", repoID, sha) + var errIns error + for i := 0; i < 5; i++ { + // in case mysql deadlock occurs, retry for a few times + // Error 1213 (40001): Deadlock found when trying to get lock; try restarting transaction + // To reproduce: + // * txn1: truncate commit_status_index; begin; update commit_status_index set max_index=max_index+1 where sha='xxx' and repo_id=1; + // * txn2: begin; update commit_status_index set max_index=max_index+1 where sha='xxx' and repo_id=1; + // * txn1: insert into `commit_status_index` (repo_id, sha, max_index) values (1, 'xxx', 0); + // * txn2: insert into `commit_status_index` (repo_id, sha, max_index) values (1, 'xxx', 0); -- then deadlock + // * then txn1 can commit, txn2 can retry and commit + _, errIns = e.Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) VALUES (?, ?, 0)", repoID, sha) + if errIns != nil && strings.Contains(errIns.Error(), "Deadlock") { + continue + } else { + break + } + } + res, err = e.Exec("UPDATE `commit_status_index` SET max_index=max_index+1 WHERE repo_id=? AND sha=?", repoID, sha) if err != nil { return 0, fmt.Errorf("update2 failed: %w", err) From 4b9f94144df25225f1ce0231bf124db5b329c099 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 16 May 2023 18:43:09 +0800 Subject: [PATCH 03/12] Use a new method for mysql generating commit status index --- models/git/commit_status.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 98174dfd42fa5..77c00ff9d765e 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -63,10 +63,35 @@ func postgresGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) return strconv.ParseInt(string(res[0]["max_index"]), 10, 64) } +func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) { + var idx int64 + // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value + return idx, db.WithTx(ctx, func(ctx context.Context) error { + if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ + "VALUES (?,?,1) ON DUPLICATE KEY UPDATE SET max_index = LAST_INSERT_ID(`commit_status_index`.max_index+1)", + // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value + repoID, sha); err != nil { + return err + } + + _, err := db.GetEngine(ctx).SQL("SELECT LAST_INSERT_ID()").Get(&idx) + if err != nil { + return err + } + if idx == 0 { + return errors.New("cannot get the correct index") + } + return nil + }) +} + // GetNextCommitStatusIndex retried 3 times to generate a resource index func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) { - if setting.Database.Type.IsPostgreSQL() { + switch { + case setting.Database.Type.IsPostgreSQL(): return postgresGetCommitStatusIndex(ctx, repoID, sha) + case setting.Database.Type.IsMySQL(): + return mysqlGetCommitStatusIndex(ctx, repoID, sha) } e := db.GetEngine(ctx) From c705ee4d08ef2ff6ee11178b79d442d6eb224aad Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 16 May 2023 21:25:02 +0800 Subject: [PATCH 04/12] Fix sql --- models/git/commit_status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index a74add6e3d475..829d830eec27b 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -69,7 +69,7 @@ func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (i // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value return idx, db.WithTx(ctx, func(ctx context.Context) error { if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ - "VALUES (?,?,1) ON DUPLICATE KEY UPDATE SET max_index = LAST_INSERT_ID(`commit_status_index`.max_index+1)", + "VALUES (?,?,1) ON DUPLICATE KEY UPDATE SET max_index = LAST_INSERT_ID(max_index+1)", // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value repoID, sha); err != nil { return err From a6ea6f9d389490ad543d56bda1397eae9f1153f3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 16 May 2023 21:26:13 +0800 Subject: [PATCH 05/12] enable commit status index parall test --- tests/integration/repo_commits_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/integration/repo_commits_test.go b/tests/integration/repo_commits_test.go index 0cfd21485d19e..57ecc4da5f743 100644 --- a/tests/integration/repo_commits_test.go +++ b/tests/integration/repo_commits_test.go @@ -7,7 +7,6 @@ import ( "fmt" "net/http" "net/http/httptest" - "os" "path" "sync" "testing" @@ -135,9 +134,6 @@ func TestRepoCommitsWithStatusRunning(t *testing.T) { } func TestRepoCommitsStatusParallel(t *testing.T) { - if os.Getenv("CI") != "" { - t.Skip("Skipping because test is flaky on CI") - } defer tests.PrepareTestEnv(t)() session := loginUser(t, "user2") From 9eeb88320246f75ca445a196fb0a23657c17643e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 3 Jun 2023 22:23:29 +0800 Subject: [PATCH 06/12] Fix SQL --- models/git/commit_status.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 829d830eec27b..0a63dd57781f6 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -69,7 +69,7 @@ func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (i // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value return idx, db.WithTx(ctx, func(ctx context.Context) error { if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ - "VALUES (?,?,1) ON DUPLICATE KEY UPDATE SET max_index = LAST_INSERT_ID(max_index+1)", + "VALUES (?,?,1) ON DUPLICATE KEY UPDATE max_index = LAST_INSERT_ID(max_index+1)", // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value repoID, sha); err != nil { return err From c0ad63901997e32a3e1dd443ecb097f0098c77b5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 3 Jun 2023 22:44:29 +0800 Subject: [PATCH 07/12] Fix resource index for mysql --- models/db/index.go | 27 ++++++++++++++++++++++++++- models/git/commit_status.go | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/models/db/index.go b/models/db/index.go index 7609d8fb6e6c2..f5926c4e38bff 100644 --- a/models/db/index.go +++ b/models/db/index.go @@ -71,10 +71,35 @@ func postgresGetNextResourceIndex(ctx context.Context, tableName string, groupID return strconv.ParseInt(string(res[0]["max_index"]), 10, 64) } +func mysqlGetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) { + var idx int64 + // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value + return idx, WithTx(ctx, func(ctx context.Context) error { + if _, err := GetEngine(ctx).Exec(fmt.Sprintf("INSERT INTO %s (group_id, max_index) "+ + "VALUES (?,LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE max_index = LAST_INSERT_ID(max_index+1)", + // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value + tableName), groupID); err != nil { + return err + } + + _, err := GetEngine(ctx).SQL("SELECT LAST_INSERT_ID()").Get(&idx) + if err != nil { + return err + } + if idx == 0 { + return errors.New("cannot get the correct index") + } + return nil + }) +} + // GetNextResourceIndex generates a resource index, it must run in the same transaction where the resource is created func GetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) { - if setting.Database.Type.IsPostgreSQL() { + switch { + case setting.Database.Type.IsPostgreSQL(): return postgresGetNextResourceIndex(ctx, tableName, groupID) + case setting.Database.Type.IsMySQL(): + return mysqlGetNextResourceIndex(ctx, tableName, groupID) } e := GetEngine(ctx) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 0a63dd57781f6..35fad185ccd76 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -69,7 +69,7 @@ func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (i // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value return idx, db.WithTx(ctx, func(ctx context.Context) error { if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ - "VALUES (?,?,1) ON DUPLICATE KEY UPDATE max_index = LAST_INSERT_ID(max_index+1)", + "VALUES (?,?,LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE max_index = LAST_INSERT_ID(max_index+1)", // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value repoID, sha); err != nil { return err From d8086d68198af47784d3f3d142ff5a639a367428 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 3 Jun 2023 22:53:01 +0800 Subject: [PATCH 08/12] add test for parally creating issue --- tests/integration/api_issue_test.go | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/integration/api_issue_test.go b/tests/integration/api_issue_test.go index 4344c15ea45f3..19408ea91def1 100644 --- a/tests/integration/api_issue_test.go +++ b/tests/integration/api_issue_test.go @@ -7,6 +7,8 @@ import ( "fmt" "net/http" "net/url" + "strconv" + "sync" "testing" "time" @@ -106,6 +108,49 @@ func TestAPICreateIssue(t *testing.T) { assert.Equal(t, repoBefore.NumClosedIssues, repoAfter.NumClosedIssues) } +func TestAPICreateIssueParallel(t *testing.T) { + defer tests.PrepareTestEnv(t)() + const body, title = "apiTestBody", "apiTestTitle" + + repoBefore := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID}) + + session := loginUser(t, owner.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo) + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token) + + var wg sync.WaitGroup + for i := 0; i < 10; i++ { + wg.Add(1) + go func(parentT *testing.T, i int) { + parentT.Run(fmt.Sprintf("ParallelCreateIssue_%d", i), func(t *testing.T) { + newTitle := title + strconv.Itoa(i) + newBody := body + strconv.Itoa(i) + req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{ + Body: newBody, + Title: newTitle, + Assignee: owner.Name, + }) + resp := MakeRequest(t, req, http.StatusCreated) + var apiIssue api.Issue + DecodeJSON(t, resp, &apiIssue) + assert.Equal(t, newBody, apiIssue.Body) + assert.Equal(t, newTitle, apiIssue.Title) + + unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ + RepoID: repoBefore.ID, + AssigneeID: owner.ID, + Content: newBody, + Title: newTitle, + }) + + wg.Done() + }) + }(t, i) + } + wg.Wait() +} + func TestAPIEditIssue(t *testing.T) { defer tests.PrepareTestEnv(t)() From 2fc3fb713cce6f0e4ce998da5fb7ac581933631b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 Jun 2023 13:04:47 +0800 Subject: [PATCH 09/12] revert unnecessary change --- models/git/commit_status.go | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 35fad185ccd76..cdf64bfaa76b7 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -108,24 +108,7 @@ func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (in } if affected == 0 { // this slow path is only for the first time of creating a resource index - var errIns error - for i := 0; i < 5; i++ { - // in case mysql deadlock occurs, retry for a few times - // Error 1213 (40001): Deadlock found when trying to get lock; try restarting transaction - // To reproduce: - // * txn1: truncate commit_status_index; begin; update commit_status_index set max_index=max_index+1 where sha='xxx' and repo_id=1; - // * txn2: begin; update commit_status_index set max_index=max_index+1 where sha='xxx' and repo_id=1; - // * txn1: insert into `commit_status_index` (repo_id, sha, max_index) values (1, 'xxx', 0); - // * txn2: insert into `commit_status_index` (repo_id, sha, max_index) values (1, 'xxx', 0); -- then deadlock - // * then txn1 can commit, txn2 can retry and commit - _, errIns = e.Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) VALUES (?, ?, 0)", repoID, sha) - if errIns != nil && strings.Contains(errIns.Error(), "Deadlock") { - continue - } else { - break - } - } - + _, errIns := e.Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) VALUES (?, ?, 0)", repoID, sha) res, err = e.Exec("UPDATE `commit_status_index` SET max_index=max_index+1 WHERE repo_id=? AND sha=?", repoID, sha) if err != nil { return 0, fmt.Errorf("update2 failed: %w", err) From 1d00c358ad106f211f3673ad70d5004f3bee67aa Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 Jun 2023 13:48:41 +0800 Subject: [PATCH 10/12] Reduce usage LAST_INSERT_ID --- models/db/index.go | 4 ++-- models/git/commit_status.go | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/models/db/index.go b/models/db/index.go index f5926c4e38bff..fbca0797e6382 100644 --- a/models/db/index.go +++ b/models/db/index.go @@ -76,13 +76,13 @@ func mysqlGetNextResourceIndex(ctx context.Context, tableName string, groupID in // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value return idx, WithTx(ctx, func(ctx context.Context) error { if _, err := GetEngine(ctx).Exec(fmt.Sprintf("INSERT INTO %s (group_id, max_index) "+ - "VALUES (?,LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE max_index = LAST_INSERT_ID(max_index+1)", + "VALUES (?,1) ON DUPLICATE KEY UPDATE max_index = max_index+1", // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value tableName), groupID); err != nil { return err } - _, err := GetEngine(ctx).SQL("SELECT LAST_INSERT_ID()").Get(&idx) + _, err := GetEngine(ctx).SQL(fmt.Sprintf("SELECT max_index FROM %s WHERE group_id = ?", tableName), groupID).Get(&idx) if err != nil { return err } diff --git a/models/git/commit_status.go b/models/git/commit_status.go index cdf64bfaa76b7..688ff746f5391 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -69,13 +69,14 @@ func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (i // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value return idx, db.WithTx(ctx, func(ctx context.Context) error { if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ - "VALUES (?,?,LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE max_index = LAST_INSERT_ID(max_index+1)", + "VALUES (?,?,1) ON DUPLICATE KEY UPDATE max_index = max_index+1", // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value repoID, sha); err != nil { return err } - _, err := db.GetEngine(ctx).SQL("SELECT LAST_INSERT_ID()").Get(&idx) + _, err := db.GetEngine(ctx).SQL("SELECT max_index FROM `commit_status_index` WHERE repo_id = ? AND sha = ?", + repoID, sha).Get(&idx) if err != nil { return err } From fa1eb066f24c78f57ae9697627198d081d7b2083 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 Jun 2023 13:55:35 +0800 Subject: [PATCH 11/12] Remove unnecessary transation check --- models/db/index.go | 32 ++++++++++++++------------------ models/git/commit_status.go | 34 +++++++++++++++------------------- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/models/db/index.go b/models/db/index.go index fbca0797e6382..259ddd6ade7ac 100644 --- a/models/db/index.go +++ b/models/db/index.go @@ -72,25 +72,21 @@ func postgresGetNextResourceIndex(ctx context.Context, tableName string, groupID } func mysqlGetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) { - var idx int64 - // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value - return idx, WithTx(ctx, func(ctx context.Context) error { - if _, err := GetEngine(ctx).Exec(fmt.Sprintf("INSERT INTO %s (group_id, max_index) "+ - "VALUES (?,1) ON DUPLICATE KEY UPDATE max_index = max_index+1", - // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value - tableName), groupID); err != nil { - return err - } + if _, err := GetEngine(ctx).Exec(fmt.Sprintf("INSERT INTO %s (group_id, max_index) "+ + "VALUES (?,1) ON DUPLICATE KEY UPDATE max_index = max_index+1", + tableName), groupID); err != nil { + return 0, err + } - _, err := GetEngine(ctx).SQL(fmt.Sprintf("SELECT max_index FROM %s WHERE group_id = ?", tableName), groupID).Get(&idx) - if err != nil { - return err - } - if idx == 0 { - return errors.New("cannot get the correct index") - } - return nil - }) + var idx int64 + _, err := GetEngine(ctx).SQL(fmt.Sprintf("SELECT max_index FROM %s WHERE group_id = ?", tableName), groupID).Get(&idx) + if err != nil { + return 0, err + } + if idx == 0 { + return 0, errors.New("cannot get the correct index") + } + return idx, nil } // GetNextResourceIndex generates a resource index, it must run in the same transaction where the resource is created diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 688ff746f5391..a018bb0553a46 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -65,26 +65,22 @@ func postgresGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) } func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) { - var idx int64 - // start a transaction to lock the mysql thread so that LAST_INSERT_ID return the correct value - return idx, db.WithTx(ctx, func(ctx context.Context) error { - if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ - "VALUES (?,?,1) ON DUPLICATE KEY UPDATE max_index = max_index+1", - // if LAST_INSERT_ID(expr) is used, next time when use LAST_INSERT_ID(), it will be given the expr value - repoID, sha); err != nil { - return err - } + if _, err := db.GetEngine(ctx).Exec("INSERT INTO `commit_status_index` (repo_id, sha, max_index) "+ + "VALUES (?,?,1) ON DUPLICATE KEY UPDATE max_index = max_index+1", + repoID, sha); err != nil { + return 0, err + } - _, err := db.GetEngine(ctx).SQL("SELECT max_index FROM `commit_status_index` WHERE repo_id = ? AND sha = ?", - repoID, sha).Get(&idx) - if err != nil { - return err - } - if idx == 0 { - return errors.New("cannot get the correct index") - } - return nil - }) + var idx int64 + _, err := db.GetEngine(ctx).SQL("SELECT max_index FROM `commit_status_index` WHERE repo_id = ? AND sha = ?", + repoID, sha).Get(&idx) + if err != nil { + return 0, err + } + if idx == 0 { + return 0, errors.New("cannot get the correct index") + } + return idx, nil } // GetNextCommitStatusIndex retried 3 times to generate a resource index From e7f016477b9f2a95dfbb32ddca70b39ae939a050 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 5 Jun 2023 16:17:22 +0800 Subject: [PATCH 12/12] Fix merge bug --- tests/integration/api_issue_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/api_issue_test.go b/tests/integration/api_issue_test.go index f332f7ff8619e..8b02342d8805b 100644 --- a/tests/integration/api_issue_test.go +++ b/tests/integration/api_issue_test.go @@ -116,7 +116,7 @@ func TestAPICreateIssueParallel(t *testing.T) { owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repoBefore.OwnerID}) session := loginUser(t, owner.Name) - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeRepo) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue) urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all&token=%s", owner.Name, repoBefore.Name, token) var wg sync.WaitGroup