mirror of
https://github.com/redis/go-redis.git
synced 2025-11-10 00:00:57 +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 {
|
func ShouldRetry(err error, retryTimeout bool) bool {
|
||||||
return shouldRetry(err, retryTimeout)
|
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 (
|
var (
|
||||||
masterAddr string
|
masterAddr string
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
@@ -890,10 +895,12 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func joinErrors(errs []error) string {
|
func joinErrors(errs []error) string {
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
if len(errs) == 1 {
|
if len(errs) == 1 {
|
||||||
return errs[0].Error()
|
return errs[0].Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
b := []byte(errs[0].Error())
|
b := []byte(errs[0].Error())
|
||||||
for _, err := range errs[1:] {
|
for _, err := range errs[1:] {
|
||||||
b = append(b, '\n')
|
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