Circuit break function may take some time to execute so it should not be executed when lock is enabled. Signed-off-by: Alex Vanin <a.vanin@yadro.com>
68 lines
1.9 KiB
Go
68 lines
1.9 KiB
Go
package tree
|
|
|
|
import (
|
|
"errors"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCircuitBreaker(t *testing.T) {
|
|
remoteErr := errors.New("service is being synchronized")
|
|
breakDuration := 1 * time.Second
|
|
threshold := 10
|
|
cb := newCircuitBreaker(breakDuration, threshold)
|
|
|
|
// Hit threshold
|
|
for i := 0; i < threshold; i++ {
|
|
err := cb.Do(1, func() error { return remoteErr })
|
|
require.ErrorIs(t, err, remoteErr)
|
|
}
|
|
|
|
// Different client should not be affected by threshold
|
|
require.NoError(t, cb.Do(2, func() error { return nil }))
|
|
|
|
// Immediate request should return circuit breaker error
|
|
require.ErrorIs(t, cb.Do(1, func() error { return nil }), ErrCBClosed)
|
|
|
|
// Request after breakDuration should be ok
|
|
time.Sleep(breakDuration)
|
|
require.NoError(t, cb.Do(1, func() error { return nil }))
|
|
|
|
// Try hitting threshold one more time after break duration
|
|
for i := 0; i < threshold; i++ {
|
|
err := cb.Do(1, func() error { return remoteErr })
|
|
require.ErrorIs(t, err, remoteErr)
|
|
}
|
|
|
|
// Immediate request should return circuit breaker error
|
|
require.ErrorIs(t, cb.Do(1, func() error { return nil }), ErrCBClosed)
|
|
}
|
|
|
|
func TestCircuitBreakerNoBlock(t *testing.T) {
|
|
remoteErr := errors.New("service is being synchronized")
|
|
funcDuration := 2 * time.Second
|
|
threshold := 100
|
|
cb := newCircuitBreaker(1*time.Minute, threshold)
|
|
|
|
slowFunc := func() error {
|
|
time.Sleep(funcDuration)
|
|
return remoteErr
|
|
}
|
|
|
|
for i := 0; i < threshold; i++ {
|
|
// run in multiple goroutines Do function and make sure it is not
|
|
go func() {
|
|
cb.Do(1, slowFunc)
|
|
}()
|
|
}
|
|
|
|
// wait for one slow func duration + some delta
|
|
time.Sleep(funcDuration + 100*time.Millisecond)
|
|
runtime.Gosched()
|
|
// expect that all goroutines were not blocked by mutex in circuit breaker
|
|
// therefore all functions are done and circuit is closed
|
|
require.ErrorIs(t, cb.Do(1, func() error { return nil }), ErrCBClosed)
|
|
}
|