frostfs-sdk-go/pool/tree/circuitbreaker_test.go
Alex Vanin 7a37613988 [#339] pool/tree: Improve code after review
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2025-03-05 14:40:45 +03:00

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)
}