Skip to content

Commit 031ddfc

Browse files
GiteaBotlunnysilverwind
authored
Fix index generation parallelly failure (#25235) (#25269)
Backport #25235 by @lunny Fix #22109 Co-authored-by: Lunny Xiao <[email protected]> Co-authored-by: silverwind <[email protected]>
1 parent d686aa0 commit 031ddfc

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

models/db/index.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,42 @@ func mysqlGetNextResourceIndex(ctx context.Context, tableName string, groupID in
8989
return idx, nil
9090
}
9191

92+
func mssqlGetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) {
93+
if _, err := GetEngine(ctx).Exec(fmt.Sprintf(`
94+
MERGE INTO %s WITH (HOLDLOCK) AS target
95+
USING (SELECT %d AS group_id) AS source
96+
(group_id)
97+
ON target.group_id = source.group_id
98+
WHEN MATCHED
99+
THEN UPDATE
100+
SET max_index = max_index + 1
101+
WHEN NOT MATCHED
102+
THEN INSERT (group_id, max_index)
103+
VALUES (%d, 1);
104+
`, tableName, groupID, groupID)); err != nil {
105+
return 0, err
106+
}
107+
108+
var idx int64
109+
_, err := GetEngine(ctx).SQL(fmt.Sprintf("SELECT max_index FROM %s WHERE group_id = ?", tableName), groupID).Get(&idx)
110+
if err != nil {
111+
return 0, err
112+
}
113+
if idx == 0 {
114+
return 0, errors.New("cannot get the correct index")
115+
}
116+
return idx, nil
117+
}
118+
92119
// GetNextResourceIndex generates a resource index, it must run in the same transaction where the resource is created
93120
func GetNextResourceIndex(ctx context.Context, tableName string, groupID int64) (int64, error) {
94121
switch {
95122
case setting.Database.Type.IsPostgreSQL():
96123
return postgresGetNextResourceIndex(ctx, tableName, groupID)
97124
case setting.Database.Type.IsMySQL():
98125
return mysqlGetNextResourceIndex(ctx, tableName, groupID)
126+
case setting.Database.Type.IsMSSQL():
127+
return mssqlGetNextResourceIndex(ctx, tableName, groupID)
99128
}
100129

101130
e := GetEngine(ctx)

models/git/commit_status.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,47 @@ func mysqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (i
8383
return idx, nil
8484
}
8585

86+
func mssqlGetCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
87+
if _, err := db.GetEngine(ctx).Exec(`
88+
MERGE INTO commit_status_index WITH (HOLDLOCK) AS target
89+
USING (SELECT ? AS repo_id, ? AS sha) AS source
90+
(repo_id, sha)
91+
ON target.repo_id = source.repo_id AND target.sha = source.sha
92+
WHEN MATCHED
93+
THEN UPDATE
94+
SET max_index = max_index + 1
95+
WHEN NOT MATCHED
96+
THEN INSERT (repo_id, sha, max_index)
97+
VALUES (?, ?, 1);
98+
`, repoID, sha, repoID, sha); err != nil {
99+
return 0, err
100+
}
101+
102+
var idx int64
103+
_, err := db.GetEngine(ctx).SQL("SELECT max_index FROM `commit_status_index` WHERE repo_id = ? AND sha = ?",
104+
repoID, sha).Get(&idx)
105+
if err != nil {
106+
return 0, err
107+
}
108+
if idx == 0 {
109+
return 0, errors.New("cannot get the correct index")
110+
}
111+
return idx, nil
112+
}
113+
86114
// GetNextCommitStatusIndex retried 3 times to generate a resource index
87115
func GetNextCommitStatusIndex(ctx context.Context, repoID int64, sha string) (int64, error) {
116+
if !git.IsValidSHAPattern(sha) {
117+
return 0, git.ErrInvalidSHA{SHA: sha}
118+
}
119+
88120
switch {
89121
case setting.Database.Type.IsPostgreSQL():
90122
return postgresGetCommitStatusIndex(ctx, repoID, sha)
91123
case setting.Database.Type.IsMySQL():
92124
return mysqlGetCommitStatusIndex(ctx, repoID, sha)
125+
case setting.Database.Type.IsMSSQL():
126+
return mssqlGetCommitStatusIndex(ctx, repoID, sha)
93127
}
94128

95129
e := db.GetEngine(ctx)

modules/git/sha1.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ func IsValidSHAPattern(sha string) bool {
2828
return shaPattern.MatchString(sha)
2929
}
3030

31+
type ErrInvalidSHA struct {
32+
SHA string
33+
}
34+
35+
func (err ErrInvalidSHA) Error() string {
36+
return fmt.Sprintf("invalid sha: %s", err.SHA)
37+
}
38+
3139
// MustID always creates a new SHA1 from a [20]byte array with no validation of input.
3240
func MustID(b []byte) SHA1 {
3341
var id SHA1

0 commit comments

Comments
 (0)