]> source.dussan.org Git - gitea.git/commitdiff
Fix upload maven pacakge parallelly (#31851)
authorLunny Xiao <xiaolunwen@gmail.com>
Sat, 21 Sep 2024 19:26:45 +0000 (03:26 +0800)
committerGitHub <noreply@github.com>
Sat, 21 Sep 2024 19:26:45 +0000 (19:26 +0000)
Use globallock for maven package uploads.

Thanks @tlusser for the test code.

Depends on ~#31813~

routers/api/packages/maven/maven.go
tests/integration/api_packages_maven_test.go

index 1486e83c57db5df98afe4ee51ab10bc8abfd518d..07e34da8e2df5cba6bb4ccf4aca907babf85abd7 100644 (file)
@@ -20,6 +20,7 @@ import (
        "strings"
 
        packages_model "code.gitea.io/gitea/models/packages"
+       "code.gitea.io/gitea/modules/globallock"
        "code.gitea.io/gitea/modules/json"
        "code.gitea.io/gitea/modules/log"
        packages_module "code.gitea.io/gitea/modules/packages"
@@ -223,6 +224,10 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
        helper.ServePackageFile(ctx, s, u, pf, opts)
 }
 
+func mavenPkgNameKey(packageName string) string {
+       return "pkg_maven_" + packageName
+}
+
 // 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 +246,14 @@ func UploadPackageFile(ctx *context.Context) {
 
        packageName := params.GroupID + "-" + params.ArtifactID
 
+       // for the same package, only one upload at a time
+       releaser, err := globallock.Lock(ctx, mavenPkgNameKey(packageName))
+       if err != nil {
+               apiError(ctx, http.StatusInternalServerError, err)
+               return
+       }
+       defer releaser()
+
        buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body)
        if err != nil {
                apiError(ctx, http.StatusInternalServerError, err)
index 0466a727b25f0d8112e11f0a93ff3616ba8dd421..e54238858c2ea01f9f1cbbe17e3c232fdaf32176 100644 (file)
@@ -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()
+       })
+}