aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2024-09-03 14:33:28 +0800
committerGitHub <noreply@github.com>2024-09-03 14:33:28 +0800
commit9c990ac043a0167dc59f1c822988ed2316f7c1df (patch)
treed0bcb53381c3775d4ebea0080e30c3309ed8604c
parentd3b0bc22c023acc7aa8e4524c1916c2d4ee41451 (diff)
downloadgitea-9c990ac043a0167dc59f1c822988ed2316f7c1df.tar.gz
gitea-9c990ac043a0167dc59f1c822988ed2316f7c1df.zip
Add lock for parallel maven upload (#31954)
Backport #31851 Fix #30171
-rw-r--r--routers/api/packages/maven/maven.go6
-rw-r--r--tests/integration/api_packages_maven_test.go33
2 files changed, 39 insertions, 0 deletions
diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go
index cb15eae682..faed8cbd61 100644
--- a/routers/api/packages/maven/maven.go
+++ b/routers/api/packages/maven/maven.go
@@ -24,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/log"
packages_module "code.gitea.io/gitea/modules/packages"
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/services/context"
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)
}
+var mavenUploadLock = sync.NewExclusivePool()
+
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.
func UploadPackageFile(ctx *context.Context) {
params, err := extractPathParameters(ctx)
@@ -241,6 +244,9 @@ func UploadPackageFile(ctx *context.Context) {
packageName := params.GroupID + "-" + params.ArtifactID
+ mavenUploadLock.CheckIn(packageName)
+ defer mavenUploadLock.CheckOut(packageName)
+
buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
diff --git a/tests/integration/api_packages_maven_test.go b/tests/integration/api_packages_maven_test.go
index 0466a727b2..e54238858c 100644
--- a/tests/integration/api_packages_maven_test.go
+++ b/tests/integration/api_packages_maven_test.go
@@ -8,6 +8,7 @@ import (
"net/http"
"strconv"
"strings"
+ "sync"
"testing"
"code.gitea.io/gitea/models/db"
@@ -252,3 +253,35 @@ func TestPackageMaven(t *testing.T) {
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()
+ })
+}