Drive circuit breaker state transitions via internal/clock

The Open->HalfOpen promotion used time.Now/time.Since directly, forcing tests
to use real time.Sleep and diverging from the project's clock convention. Add
an unexported withClock option (default clock.System) and replace the real
sleeps in tests with mock-clock Advance, making the transitions deterministic
and the package faster.
This commit is contained in:
2026-05-23 13:47:26 +03:00
parent 43d3ecfba1
commit b07d487e63
3 changed files with 32 additions and 9 deletions

View File

@@ -1,11 +1,16 @@
package circuitbreaker
import "time"
import (
"time"
"git.codelab.vc/pkg/httpx/internal/clock"
)
type options struct {
failureThreshold int // consecutive failures to trip
openDuration time.Duration // how long to stay open before half-open
halfOpenMax int // max concurrent requests in half-open
clk clock.Clock // time source (real by default)
}
func defaults() options {
@@ -13,12 +18,23 @@ func defaults() options {
failureThreshold: 5,
openDuration: 30 * time.Second,
halfOpenMax: 1,
clk: clock.System(),
}
}
// Option configures a Breaker.
type Option func(*options)
// withClock sets the clock used for state-transition timing. Unexported; for
// deterministic tests.
func withClock(c clock.Clock) Option {
return func(o *options) {
if c != nil {
o.clk = c
}
}
}
// WithFailureThreshold sets the number of consecutive failures required to
// trip the breaker from Closed to Open. Default is 5.
func WithFailureThreshold(n int) Option {