Skip to content

Commit e31cdf5

Browse files
committed
refactor: also move ewma+half-open check into option
1 parent f4ef83d commit e31cdf5

File tree

3 files changed

+21
-12
lines changed

3 files changed

+21
-12
lines changed

breaker.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package hoglet
22

33
import (
4+
"fmt"
45
"math"
56
"sync/atomic"
67
"time"
@@ -123,6 +124,14 @@ func (e *EWMABreaker) observe(halfOpen, failure bool) stateChange {
123124
}
124125
}
125126

127+
// apply implements Option.
128+
func (e *EWMABreaker) apply(o *options) error {
129+
if o.halfOpenDelay == 0 {
130+
return fmt.Errorf("EWMABreaker requires a half-open delay")
131+
}
132+
return nil
133+
}
134+
126135
// SlidingWindowBreaker is a [Breaker] that uses a sliding window to determine the error rate.
127136
type SlidingWindowBreaker struct {
128137
windowSize time.Duration
@@ -208,8 +217,6 @@ func (s *SlidingWindowBreaker) observe(halfOpen, failure bool) stateChange {
208217
}
209218
}
210219

211-
var _ Option = (*SlidingWindowBreaker)(nil)
212-
213220
// apply implements Option.
214221
func (s *SlidingWindowBreaker) apply(o *options) error {
215222
if o.halfOpenDelay == 0 || o.halfOpenDelay > s.windowSize {

hoglet.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ type Breaker interface {
4242
// The halfOpen parameter indicates whether the call was made in half-open state.
4343
// The failure parameter indicates whether the call failed.
4444
observe(halfOpen, failure bool) stateChange
45+
46+
Option // breakers can also modify or sanity-check their circuit's options
4547
}
4648

4749
// ObserverFactory is an interface that allows customizing the per-call observer creation.
@@ -87,6 +89,8 @@ func NewCircuit[IN, OUT any](f WrappedFunc[IN, OUT], breaker Breaker, opts ...Op
8789

8890
if breaker != nil {
8991
o.breaker = breaker
92+
// apply breaker as last, so it can verify
93+
opts = append(opts, breaker)
9094
}
9195

9296
// the default observerFactory is the circuit itself
@@ -98,18 +102,8 @@ func NewCircuit[IN, OUT any](f WrappedFunc[IN, OUT], breaker Breaker, opts ...Op
98102
}
99103
}
100104

101-
if breakerOpt, ok := breaker.(Option); ok {
102-
if err := breakerOpt.apply(&o); err != nil {
103-
return nil, fmt.Errorf("applying breaker option: %w", err)
104-
}
105-
}
106-
107105
c.options = o
108106

109-
if _, ok := breaker.(*EWMABreaker); ok && c.halfOpenDelay == 0 {
110-
return nil, fmt.Errorf("EWMABreaker requires a half-open delay")
111-
}
112-
113107
return c, nil
114108
}
115109

@@ -297,3 +291,7 @@ type noopBreaker struct{}
297291
func (noopBreaker) observe(halfOpen, failure bool) stateChange {
298292
return stateChangeNone
299293
}
294+
295+
func (noopBreaker) apply(*options) error {
296+
return nil
297+
}

hoglet_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ func (mt *mockBreaker) observe(halfOpen, failure bool) stateChange {
122122
return stateChangeClose
123123
}
124124

125+
func (mt *mockBreaker) apply(o *options) error {
126+
return nil
127+
}
128+
125129
func TestHoglet_Do(t *testing.T) {
126130
type calls struct {
127131
arg noopIn

0 commit comments

Comments
 (0)