Skip to content

Commit

Permalink
refactor: also move ewma+half-open check into option
Browse files Browse the repository at this point in the history
  • Loading branch information
costela committed Jan 24, 2024
1 parent 9a8a4be commit 30044d1
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 12 deletions.
11 changes: 9 additions & 2 deletions breaker.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package hoglet

import (
"fmt"
"math"
"sync/atomic"
"time"
Expand Down Expand Up @@ -123,6 +124,14 @@ func (e *EWMABreaker) observe(halfOpen, failure bool) stateChange {
}
}

// apply implements Option.
func (e *EWMABreaker) apply(o *options) error {
if o.halfOpenDelay == 0 {
return fmt.Errorf("EWMABreaker requires a half-open delay")
}
return nil
}

// SlidingWindowBreaker is a [Breaker] that uses a sliding window to determine the error rate.
type SlidingWindowBreaker struct {
windowSize time.Duration
Expand Down Expand Up @@ -208,8 +217,6 @@ func (s *SlidingWindowBreaker) observe(halfOpen, failure bool) stateChange {
}
}

var _ Option = (*SlidingWindowBreaker)(nil)

// apply implements Option.
func (s *SlidingWindowBreaker) apply(o *options) error {
if o.halfOpenDelay == 0 || o.halfOpenDelay > s.windowSize {
Expand Down
18 changes: 8 additions & 10 deletions hoglet.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type Breaker interface {
// The halfOpen parameter indicates whether the call was made in half-open state.
// The failure parameter indicates whether the call failed.
observe(halfOpen, failure bool) stateChange

Option // breakers can also modify or sanity-check their circuit's options
}

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

if breaker != nil {
o.breaker = breaker
// apply breaker as last, so it can verify
opts = append(opts, breaker)
}

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

if breakerOpt, ok := breaker.(Option); ok {
if err := breakerOpt.apply(&o); err != nil {
return nil, fmt.Errorf("applying breaker option: %w", err)
}
}

c.options = o

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

return c, nil
}

Expand Down Expand Up @@ -297,3 +291,7 @@ type noopBreaker struct{}
func (noopBreaker) observe(halfOpen, failure bool) stateChange {
return stateChangeNone
}

func (noopBreaker) apply(*options) error {
return nil
}
4 changes: 4 additions & 0 deletions hoglet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ func (mt *mockBreaker) observe(halfOpen, failure bool) stateChange {
return stateChangeClose
}

func (mt *mockBreaker) apply(o *options) error {
return nil
}

func TestHoglet_Do(t *testing.T) {
type calls struct {
arg noopIn
Expand Down

0 comments on commit 30044d1

Please sign in to comment.