internal/resilience/circuit_breaker_test.go (TestCircuitBreakerResetsStaleHalfOpenAttempts, ~line 311) opens the circuit, sleeps openTimeout * 2, reserves the single half-open slot, then asserts the second Allow() is rejected. Under -race on a loaded CI runner the goroutine can be descheduled long enough that StaleAttemptTimeout elapses before the second Allow(), so the stale-reset path fires and the request is allowed — failing expected second request to be rejected when half-open slots exhausted.
Observed on PR #582 run 30439850300 (no actual data race reported); passed on re-run with no code change.
Fix suggestion: drive the breaker with an injected clock instead of real time.Sleep micro-timeouts, or widen StaleAttemptTimeout far past the test's real-time window so scheduler jitter can't cross it.
internal/resilience/circuit_breaker_test.go(TestCircuitBreakerResetsStaleHalfOpenAttempts, ~line 311) opens the circuit, sleepsopenTimeout * 2, reserves the single half-open slot, then asserts the secondAllow()is rejected. Under-raceon a loaded CI runner the goroutine can be descheduled long enough thatStaleAttemptTimeoutelapses before the secondAllow(), so the stale-reset path fires and the request is allowed — failingexpected second request to be rejected when half-open slots exhausted.Observed on PR #582 run 30439850300 (no actual data race reported); passed on re-run with no code change.
Fix suggestion: drive the breaker with an injected clock instead of real
time.Sleepmicro-timeouts, or widenStaleAttemptTimeoutfar past the test's real-time window so scheduler jitter can't cross it.