forked from TrueCloudLab/frostfs-sdk-go
68 lines
1.8 KiB
Go
68 lines
1.8 KiB
Go
package tree
|
|
|
|
import (
|
|
"errors"
|
|
"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 := 200 * time.Millisecond
|
|
threshold := 100
|
|
cb := newCircuitBreaker(10*funcDuration, threshold)
|
|
|
|
slowFunc := func() error {
|
|
time.Sleep(funcDuration)
|
|
return remoteErr
|
|
}
|
|
|
|
for i := 0; i < threshold; i++ {
|
|
// run in multiple goroutines Do function
|
|
go func() {
|
|
cb.Do(1, slowFunc)
|
|
}()
|
|
}
|
|
|
|
time.Sleep(funcDuration)
|
|
|
|
// eventually at most after one more func duration circuit breaker will be
|
|
// closed and not blocked by slow func execution under mutex
|
|
require.Eventually(t, func() bool {
|
|
return errors.Is(cb.Do(1, func() error { return nil }), ErrCBClosed)
|
|
}, funcDuration, funcDuration/10)
|
|
}
|