Add lock for parallel maven upload (#31954)

Backport #31851 
Fix #30171
This commit is contained in:
Lunny Xiao 2024-09-03 14:33:28 +08:00 committed by GitHub
parent d3b0bc22c0
commit 9c990ac043
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 39 additions and 0 deletions

View File

@ -24,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages" packages_module "code.gitea.io/gitea/modules/packages"
maven_module "code.gitea.io/gitea/modules/packages/maven" maven_module "code.gitea.io/gitea/modules/packages/maven"
"code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/routers/api/packages/helper" "code.gitea.io/gitea/routers/api/packages/helper"
"code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/context"
packages_service "code.gitea.io/gitea/services/packages" packages_service "code.gitea.io/gitea/services/packages"
@ -223,6 +224,8 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
helper.ServePackageFile(ctx, s, u, pf, opts) helper.ServePackageFile(ctx, s, u, pf, opts)
} }
var mavenUploadLock = sync.NewExclusivePool()
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created. // UploadPackageFile adds a file to the package. If the package does not exist, it gets created.
func UploadPackageFile(ctx *context.Context) { func UploadPackageFile(ctx *context.Context) {
params, err := extractPathParameters(ctx) params, err := extractPathParameters(ctx)
@ -241,6 +244,9 @@ func UploadPackageFile(ctx *context.Context) {
packageName := params.GroupID + "-" + params.ArtifactID packageName := params.GroupID + "-" + params.ArtifactID
mavenUploadLock.CheckIn(packageName)
defer mavenUploadLock.CheckOut(packageName)
buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body) buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body)
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)

View File

@ -8,6 +8,7 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"sync"
"testing" "testing"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -252,3 +253,35 @@ func TestPackageMaven(t *testing.T) {
assert.True(t, test.IsNormalPageCompleted(resp.Body.String())) assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
}) })
} }
func TestPackageMavenConcurrent(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
groupID := "com.gitea"
artifactID := "test-project"
packageVersion := "1.0.1"
root := fmt.Sprintf("/api/packages/%s/maven/%s/%s", user.Name, strings.ReplaceAll(groupID, ".", "/"), artifactID)
putFile := func(t *testing.T, path, content string, expectedStatus int) {
req := NewRequestWithBody(t, "PUT", root+path, strings.NewReader(content)).
AddBasicAuth(user.Name)
MakeRequest(t, req, expectedStatus)
}
t.Run("Concurrent Upload", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
putFile(t, fmt.Sprintf("/%s/%s.jar", packageVersion, strconv.Itoa(i)), "test", http.StatusCreated)
wg.Done()
}(i)
}
wg.Wait()
})
}