mirror of
https://github.com/redis/go-redis.git
synced 2025-11-08 13:02:18 +03:00
fix(sentinel): handle empty address (#3577)
* improvements * linter fixes * prevention on unnecessary allocations in case of bad configuration * Test/Benchmark, old code with safety harness preventing panic --------- Co-authored-by: manish <manish.sharma@manifestit.io> Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
This commit is contained in:
@@ -106,3 +106,7 @@ func (c *ModuleLoadexConfig) ToArgs() []interface{} {
|
||||
func ShouldRetry(err error, retryTimeout bool) bool {
|
||||
return shouldRetry(err, retryTimeout)
|
||||
}
|
||||
|
||||
func JoinErrors(errs []error) string {
|
||||
return joinErrors(errs)
|
||||
}
|
||||
|
||||
@@ -843,6 +843,11 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// short circuit if no sentinels configured
|
||||
if len(c.sentinelAddrs) == 0 {
|
||||
return "", errors.New("redis: no sentinels configured")
|
||||
}
|
||||
|
||||
var (
|
||||
masterAddr string
|
||||
wg sync.WaitGroup
|
||||
@@ -890,10 +895,12 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
func joinErrors(errs []error) string {
|
||||
if len(errs) == 0 {
|
||||
return ""
|
||||
}
|
||||
if len(errs) == 1 {
|
||||
return errs[0].Error()
|
||||
}
|
||||
|
||||
b := []byte(errs[0].Error())
|
||||
for _, err := range errs[1:] {
|
||||
b = append(b, '\n')
|
||||
|
||||
@@ -682,3 +682,99 @@ func compareSlices(t *testing.T, a, b []string, name string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type joinErrorsTest struct {
|
||||
name string
|
||||
errs []error
|
||||
expected string
|
||||
}
|
||||
|
||||
func TestJoinErrors(t *testing.T) {
|
||||
tests := []joinErrorsTest{
|
||||
{
|
||||
name: "empty slice",
|
||||
errs: []error{},
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "single error",
|
||||
errs: []error{errors.New("first error")},
|
||||
expected: "first error",
|
||||
},
|
||||
{
|
||||
name: "two errors",
|
||||
errs: []error{errors.New("first error"), errors.New("second error")},
|
||||
expected: "first error\nsecond error",
|
||||
},
|
||||
{
|
||||
name: "multiple errors",
|
||||
errs: []error{
|
||||
errors.New("first error"),
|
||||
errors.New("second error"),
|
||||
errors.New("third error"),
|
||||
},
|
||||
expected: "first error\nsecond error\nthird error",
|
||||
},
|
||||
{
|
||||
name: "nil slice",
|
||||
errs: nil,
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := redis.JoinErrors(tt.errs)
|
||||
if result != tt.expected {
|
||||
t.Errorf("joinErrors() = %q, want %q", result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkJoinErrors(b *testing.B) {
|
||||
benchmarks := []joinErrorsTest{
|
||||
{
|
||||
name: "empty slice",
|
||||
errs: []error{},
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "single error",
|
||||
errs: []error{errors.New("first error")},
|
||||
expected: "first error",
|
||||
},
|
||||
{
|
||||
name: "two errors",
|
||||
errs: []error{errors.New("first error"), errors.New("second error")},
|
||||
expected: "first error\nsecond error",
|
||||
},
|
||||
{
|
||||
name: "multiple errors",
|
||||
errs: []error{
|
||||
errors.New("first error"),
|
||||
errors.New("second error"),
|
||||
errors.New("third error"),
|
||||
},
|
||||
expected: "first error\nsecond error\nthird error",
|
||||
},
|
||||
{
|
||||
name: "nil slice",
|
||||
errs: nil,
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
result := redis.JoinErrors(bm.errs)
|
||||
if result != bm.expected {
|
||||
b.Errorf("joinErrors() = %q, want %q", result, bm.expected)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user