Esempio n. 1
0
// DefaultCircuitBreakerConfig creates a circuit breaker config usign the
// default values for timeouts and half-closed retry probability, a constant
// retry backoff of 1000ms, an any-error failure interpreter, and a trip
// condition which fires only after five ocnsecutive failures.
func DefaultCircuitBreakerConfig() *CircuitBreakerConfig {
	return &CircuitBreakerConfig{
		InvocationTimeout:          DefaultInvocationTimeout,
		HalfClosedRetryProbability: DefaultHalfClosedRetryProbability,
		ResetBackoff:               backoff.NewConstantBackoff(1000 * time.Millisecond),
		FailureInterpreter:         NewAnyErrorFailureInterpreter(),
		TripCondition:              NewConsecutiveFailureTripCondition(5),
	}
}
Esempio n. 2
0
func (s *OvercurrentSuite) TestTimeoutDisabled(c *C) {
	cb := NewCircuitBreaker(&CircuitBreakerConfig{
		InvocationTimeout:          0,
		ResetBackoff:               backoff.NewConstantBackoff(250 * time.Millisecond),
		HalfClosedRetryProbability: 1,
		FailureInterpreter:         NewAnyErrorFailureInterpreter(),
		TripCondition:              NewConsecutiveFailureTripCondition(5),
	})

	fn := func() error {
		<-time.After(250 * time.Millisecond)
		return nil
	}

	c.Assert(cb.Call(fn), Equals, nil)
}
Esempio n. 3
0
func (s *OvercurrentSuite) TestHalfOpenReset(c *C) {
	cb := NewCircuitBreaker(&CircuitBreakerConfig{
		InvocationTimeout:          DefaultInvocationTimeout,
		ResetBackoff:               backoff.NewConstantBackoff(250 * time.Millisecond),
		HalfClosedRetryProbability: 1,
		FailureInterpreter:         NewAnyErrorFailureInterpreter(),
		TripCondition:              NewConsecutiveFailureTripCondition(5),
	})

	err := errors.New("Test error.")
	fn1 := func() error { return err }
	fn2 := func() error { return nil }

	for i := 0; i < 5; i++ {
		c.Assert(cb.Call(fn1), Equals, err)
	}

	c.Assert(cb.Call(fn1), Equals, ErrCircuitOpen)
	<-time.After(250 * time.Millisecond)
	c.Assert(cb.Call(fn2), Equals, nil)
}
Esempio n. 4
0
func (s *OvercurrentSuite) TestHardTrip(c *C) {
	cb := NewCircuitBreaker(&CircuitBreakerConfig{
		InvocationTimeout:          DefaultInvocationTimeout,
		ResetBackoff:               backoff.NewConstantBackoff(250 * time.Millisecond),
		HalfClosedRetryProbability: 1,
		FailureInterpreter:         NewAnyErrorFailureInterpreter(),
		TripCondition:              NewConsecutiveFailureTripCondition(1),
	})

	fn := func() error {
		return nil
	}

	c.Assert(cb.Call(fn), Equals, nil)
	cb.Trip()

	c.Assert(cb.Call(fn), Equals, ErrCircuitOpen)
	<-time.After(250 * time.Millisecond)
	c.Assert(cb.Call(fn), Equals, ErrCircuitOpen)

	cb.Reset()
	c.Assert(cb.Call(fn), Equals, nil)
}
Esempio n. 5
0
func (s *OvercurrentSuite) TestHalfOpenProbability(c *C) {
	runs := 5000
	prob := .25
	dist := .01

	success := 0
	failure := 0

	fn1 := func() error { return errors.New("Test error.") }
	fn2 := func() error {
		success++
		return nil
	}

	for i := 0; i < runs; i++ {
		cb := NewCircuitBreaker(&CircuitBreakerConfig{
			InvocationTimeout:          DefaultInvocationTimeout,
			ResetBackoff:               backoff.NewConstantBackoff(1 * time.Nanosecond),
			HalfClosedRetryProbability: prob,
			FailureInterpreter:         NewAnyErrorFailureInterpreter(),
			TripCondition:              NewConsecutiveFailureTripCondition(1),
		})

		cb.Call(fn1)
		<-time.After(1 * time.Nanosecond)

		if cb.Call(fn2) == ErrCircuitOpen {
			failure++
		}
	}

	lower := int(float64(runs)*prob - float64(runs)*dist)
	upper := int(float64(runs)*prob + float64(runs)*dist)

	c.Assert(success+failure, Equals, runs)
	c.Assert(lower <= success && success <= upper, Equals, true)
}