mirror of
https://github.com/go-gitea/gitea.git
synced 2026-11-04 07:41:13 +00:00
Backport #40167 by @perfectra1n The `repo_stats_update` queue only deduplicates waiting items, so several workers can index the same repository at once, then `UpdateLanguageStats` can lead to transaction deadlock. Use a global lock to avoid concurrent updates, and also helps https://github.com/go-gitea/gitea/pull/39342 to avoid duplicate updates. Co-authored-by: Jon Fuller <jonfuller2012@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
3 files changed
+37
-1
No files matched your search
@@ -151,7 +151,7 @@ func UpdateLanguageStats(ctx context.Context, repo *Repository, commitID string,
|
||||
var topLang string
|
||||
var s int64
|
||||
for lang, size := range stats {
|
||||
if size > s {
|
||||
if size > s || (size == s && lang < topLang) {
|
||||
s = size
|
||||
topLang = lang
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUpdateLanguageStatsPrimaryTie(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
|
||||
require.NoError(t, repo_model.UpdateLanguageStats(t.Context(), repo, "1234567890", map[string]int64{"Go": 10, "C": 10}))
|
||||
|
||||
stats, err := repo_model.GetLanguageStats(t.Context(), repo)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, stats, 2)
|
||||
for _, stat := range stats {
|
||||
assert.Equal(t, stat.Language == "C", stat.IsPrimary, stat.Language)
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/languagestats"
|
||||
"gitea.dev/modules/globallock"
|
||||
"gitea.dev/modules/graceful"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/process"
|
||||
@@ -23,6 +24,13 @@ func (db *DBIndexer) Index(id int64) error {
|
||||
ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().ShutdownContext(), fmt.Sprintf("Stats.DB Index Repo[%d]", id))
|
||||
defer finished()
|
||||
|
||||
// the unique queue doesn't stop two workers from indexing the same repository at once
|
||||
releaser, err := globallock.Lock(ctx, fmt.Sprintf("repo_stats_index_%d", id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer releaser()
|
||||
|
||||
repo, err := repo_model.GetRepositoryByID(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in new issue
Block a user