From ba3fd257a3fdbec3b5db98971f7112120e77aed8 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 3 Nov 2026 20:47:43 -0800 Subject: [PATCH] filer: clear a dead test replica's reachability record before closing it (#12387) * filer: clear a dead test replica's reachability record before closing it The read path tries hosts that recently failed last. A dead test server can land on a port an earlier test left marked as failed, so the live replica answered first, nothing failed and the location refresh under test never ran. Have the dead replica answer once through util_http so its record is cleared before it closes. Co-Authored-By: Claude Opus 5.5 * filer: close the dead test replica when reaching it fails Co-Authored-By: Claude Opus 5.5 * filer: clear the live test replica's reachability record too Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- weed/filer/filechunk_manifest_test.go | 8 ++++---- weed/filer/reader_cache_test.go | 24 +++++++++++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/weed/filer/filechunk_manifest_test.go b/weed/filer/filechunk_manifest_test.go index 5e82c70459..039399f31e 100644 --- a/weed/filer/filechunk_manifest_test.go +++ b/weed/filer/filechunk_manifest_test.go @@ -652,10 +652,10 @@ func TestFetchWholeChunkRefreshesLocationsAfterPartialFailure(t *testing.T) { }) assert.NoError(t, err) - liveURL := manifestServer(t, manifestBytes).URL + "/5,abc" - dead := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - deadURL := dead.URL - dead.Close() + live := manifestServer(t, manifestBytes) + reachServer(t, live) + liveURL := live.URL + "/5,abc" + deadURL := deadServerURL(t) lookup := &stagedLookup{ staleUrls: []string{deadURL + "/5,abc", liveURL}, diff --git a/weed/filer/reader_cache_test.go b/weed/filer/reader_cache_test.go index 16c3531f50..faf184f878 100644 --- a/weed/filer/reader_cache_test.go +++ b/weed/filer/reader_cache_test.go @@ -160,9 +160,8 @@ func TestReaderCacheRefreshesLocationsAfterPartialFailure(t *testing.T) { w.Write(payload) })) defer live.Close() - dead := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - deadURL := dead.URL - dead.Close() + reachServer(t, live) + deadURL := deadServerURL(t) fileId := "3,abc" invalidator := &mockCacheInvalidatorForReaderCache{} @@ -191,6 +190,25 @@ func TestReaderCacheRefreshesLocationsAfterPartialFailure(t *testing.T) { } } +// reachServer has srv answer one request. The read path orders replicas by +// whether their host recently failed, and srv's port may be one an earlier test +// left marked as failed, so the answer clears that record. +func reachServer(t *testing.T, srv *httptest.Server) { + t.Helper() + if _, _, err := util_http.Get(srv.URL); err != nil { + t.Fatalf("reach %s: %v", srv.URL, err) + } +} + +// deadServerURL is a replica that answered once and then went away. +func deadServerURL(t *testing.T) string { + t.Helper() + dead := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) + defer dead.Close() + reachServer(t, dead) + return dead.URL +} + func TestReaderCacheRemovesFailedDownloader(t *testing.T) { cache := newMockChunkCacheForReaderCache() fileId := "425141,failed"