Skip to content

Commit 5de4173

Browse files
authored
Fix upload maven pacakge parallelly (#31851)
Use globallock for maven package uploads. Thanks @tlusser for the test code. Depends on ~#31813~
1 parent ebfde84 commit 5de4173

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

routers/api/packages/maven/maven.go

+13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"strings"
2121

2222
packages_model "code.gitea.io/gitea/models/packages"
23+
"code.gitea.io/gitea/modules/globallock"
2324
"code.gitea.io/gitea/modules/json"
2425
"code.gitea.io/gitea/modules/log"
2526
packages_module "code.gitea.io/gitea/modules/packages"
@@ -223,6 +224,10 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
223224
helper.ServePackageFile(ctx, s, u, pf, opts)
224225
}
225226

227+
func mavenPkgNameKey(packageName string) string {
228+
return "pkg_maven_" + packageName
229+
}
230+
226231
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.
227232
func UploadPackageFile(ctx *context.Context) {
228233
params, err := extractPathParameters(ctx)
@@ -241,6 +246,14 @@ func UploadPackageFile(ctx *context.Context) {
241246

242247
packageName := params.GroupID + "-" + params.ArtifactID
243248

249+
// for the same package, only one upload at a time
250+
releaser, err := globallock.Lock(ctx, mavenPkgNameKey(packageName))
251+
if err != nil {
252+
apiError(ctx, http.StatusInternalServerError, err)
253+
return
254+
}
255+
defer releaser()
256+
244257
buf, err := packages_module.CreateHashedBufferFromReader(ctx.Req.Body)
245258
if err != nil {
246259
apiError(ctx, http.StatusInternalServerError, err)

tests/integration/api_packages_maven_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"strconv"
1010
"strings"
11+
"sync"
1112
"testing"
1213

1314
"code.gitea.io/gitea/models/db"
@@ -252,3 +253,35 @@ func TestPackageMaven(t *testing.T) {
252253
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
253254
})
254255
}
256+
257+
func TestPackageMavenConcurrent(t *testing.T) {
258+
defer tests.PrepareTestEnv(t)()
259+
260+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
261+
262+
groupID := "com.gitea"
263+
artifactID := "test-project"
264+
packageVersion := "1.0.1"
265+
266+
root := fmt.Sprintf("/api/packages/%s/maven/%s/%s", user.Name, strings.ReplaceAll(groupID, ".", "/"), artifactID)
267+
268+
putFile := func(t *testing.T, path, content string, expectedStatus int) {
269+
req := NewRequestWithBody(t, "PUT", root+path, strings.NewReader(content)).
270+
AddBasicAuth(user.Name)
271+
MakeRequest(t, req, expectedStatus)
272+
}
273+
274+
t.Run("Concurrent Upload", func(t *testing.T) {
275+
defer tests.PrintCurrentTest(t)()
276+
277+
var wg sync.WaitGroup
278+
for i := 0; i < 10; i++ {
279+
wg.Add(1)
280+
go func(i int) {
281+
putFile(t, fmt.Sprintf("/%s/%s.jar", packageVersion, strconv.Itoa(i)), "test", http.StatusCreated)
282+
wg.Done()
283+
}(i)
284+
}
285+
wg.Wait()
286+
})
287+
}

0 commit comments

Comments
 (0)