From 809654920fc90ab2f34c43f65b7fdbb714ce702f Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Sun, 25 Oct 2026 20:27:05 +1100 Subject: [PATCH 1/2] Gate repodata coalescing tests on singleflight waiters --- .../rpm/github_repodata_cache_test.go | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/internal/provider/rpm/github_repodata_cache_test.go b/internal/provider/rpm/github_repodata_cache_test.go index 6cd5388..a7fd9c5 100644 --- a/internal/provider/rpm/github_repodata_cache_test.go +++ b/internal/provider/rpm/github_repodata_cache_test.go @@ -5,6 +5,7 @@ import ( "errors" "net/http" "net/http/httptest" + "runtime" "strings" "sync" "testing" @@ -206,18 +207,35 @@ func TestCachedRepodataEvictsIdleRemotes(t *testing.T) { } } -// waitFor polls until cond holds, then gives goroutines that passed the -// fingerprint a moment to reach the singleflight call. func waitFor(t *testing.T, cond func() bool) { t.Helper() - deadline := time.Now().Add(5 * time.Second) + deadline := time.Now().Add(10 * time.Second) for !cond() { if time.Now().After(deadline) { t.Fatal("condition not reached") } time.Sleep(time.Millisecond) } - time.Sleep(50 * time.Millisecond) +} + +// sfWaiters counts goroutines parked on an in-flight singleflight call. +func sfWaiters() int { + buf := make([]byte, 1<<20) + for { + n := runtime.Stack(buf, true) + if n < len(buf) { + buf = buf[:n] + break + } + buf = make([]byte, 2*len(buf)) + } + waiters := 0 + for _, g := range strings.Split(string(buf), "\n\n") { + if strings.Contains(g, "sync.(*WaitGroup).Wait") && strings.Contains(g, "singleflight.(*Group).Do(") { + waiters++ + } + } + return waiters } func TestCachedRepodataCoalescesConcurrentBuilds(t *testing.T) { @@ -234,7 +252,7 @@ func TestCachedRepodataCoalescesConcurrentBuilds(t *testing.T) { codes[i] = serveReq(t, p, remote, store, httptest.NewRequest(http.MethodGet, "/x", nil), repodataPaths[i%len(repodataPaths)]).Code }() } - waitFor(t, func() bool { return store.fpCount() == n }) + waitFor(t, func() bool { return store.listCount() == 1 && sfWaiters() == n-1 }) close(gate) wg.Wait() for i, c := range codes { @@ -261,7 +279,7 @@ func TestCachedRepodataLeaderCancelDoesNotFailWaiters(t *testing.T) { go func() { results <- serveReq(t, p, remote, store, httptest.NewRequest(http.MethodGet, "/x", nil), "repodata/repomd.xml").Code }() - waitFor(t, func() bool { return store.fpCount() == 2 }) + waitFor(t, func() bool { return sfWaiters() == 1 }) cancelLeader() close(gate) for range 2 { -- 2.47.3 From dd7c90d1a195e50105ab48eb6bbd75f786eefe9e Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Sun, 25 Oct 2026 20:41:43 +1100 Subject: [PATCH 2/2] Retrigger CI -- 2.47.3