From ad41b9bb7b887b48eecceb0b0e9f95c570e9bf3e Mon Sep 17 00:00:00 2001 From: Kpa-clawbot Date: Sat, 6 Jun 2026 21:59:23 -0700 Subject: [PATCH] fix(tests): subpaths_window tests wait for index readiness after #1595 chunked load (#1621) ## Why master is red After PRs #1592 (route-window subpath regression test) and #1595 (background/chunked index build with 503 readiness gate) were merged together, two tests in `cmd/server/subpaths_window_test.go` started failing on master: ``` --- FAIL: TestSubpathsHonorsTimeWindow_StoreLevel subpaths_window_test.go:70: unbounded: expected totalPaths=2, got 0 (subpaths=[]) --- FAIL: TestSubpathsHandlerHonorsTimeWindow subpaths_window_test.go:116: GET /api/analytics/subpaths?...: status=503 body={"error":"index loading","retryAfter":5} ``` Both branches passed in isolation; the conflict only manifested post-merge. Reason: - **#1592** added tests that call `store.Load()` then immediately query `GetAnalyticsSubpathsWithWindow` / hit `/api/analytics/subpaths`. - **#1595** moved the subpath + path-hop index builds off the critical path of `Load()` into background goroutines, and hard-gated the analytics handlers behind `SubpathIndexReady()` (returning 503 + `Retry-After: 5` until the build completes). So after `Load()` returns, `s.spIndex` is still empty for a short window and the handler returns 503. The store-level test sees `totalPaths=0`; the handler test sees the 503. ## Fix (test-only) Add `store.WaitIndexesReady(5 * time.Second)` between `Load()` and the assertions in both tests. This matches the established pattern already used by `routes_test.go` and `repeater_enrich_recomputer_1008_test.go`. The 503 readiness gate from #1595 is intentional production behavior and is **not** touched. No production code is modified. ## Repro Before: ``` $ go test ./cmd/server/ -run TestSubpaths.*Window -v -count=1 --- FAIL: TestSubpathsHonorsTimeWindow_StoreLevel (0.01s) subpaths_window_test.go:70: unbounded: expected totalPaths=2, got 0 (subpaths=[]) --- FAIL: TestSubpathsHandlerHonorsTimeWindow (0.02s) subpaths_window_test.go:116: GET /api/analytics/subpaths?minLen=2&maxLen=8: status=503 body={"error":"index loading","retryAfter":5} FAIL ``` After: ``` $ go test ./cmd/server/ -run TestSubpaths.*Window -v -count=3 --- PASS: TestSubpathsHonorsTimeWindow_StoreLevel (0.01s) --- PASS: TestSubpathsHandlerHonorsTimeWindow (0.02s) ... (x3) ... PASS ok github.com/corescope/server 0.097s $ go test ./cmd/server/ -count=1 -timeout 300s ok github.com/corescope/server 46.292s ``` ## Files changed - `cmd/server/subpaths_window_test.go` (+11 lines, test-only) ## Notes - TDD exemption: this is a test-fix PR for a merge-conflict-induced failure. The "failing test" already exists on master; this PR makes it pass correctly by waiting on the readiness gate the test was previously unaware of. - Unblocks staging deploys. Co-authored-by: openclaw-bot --- cmd/server/subpaths_window_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cmd/server/subpaths_window_test.go b/cmd/server/subpaths_window_test.go index 01be95aa..933dbff6 100644 --- a/cmd/server/subpaths_window_test.go +++ b/cmd/server/subpaths_window_test.go @@ -62,6 +62,11 @@ func TestSubpathsHonorsTimeWindow_StoreLevel(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load failed: %v", err) } + // #1008: indexes build in the background after Load(); tests that + // read s.spIndex / s.spTxIndex must wait for the ready flag. + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatalf("indexes not ready after 5s") + } // Unbounded: should see both transmissions and their subpaths. all := store.GetAnalyticsSubpathsWithWindow("", 2, 8, 100, TimeWindow{}) @@ -101,6 +106,12 @@ func TestSubpathsHandlerHonorsTimeWindow(t *testing.T) { if err := store.Load(); err != nil { t.Fatalf("store.Load failed: %v", err) } + // #1008: handler is hard-gated behind SubpathIndexReady() and returns + // 503 until the background build completes. Wait for ready before + // hitting the route. + if !store.WaitIndexesReady(5 * time.Second) { + t.Fatalf("indexes not ready after 5s") + } srv.store = store mustGet := func(url string) map[string]interface{} {