Chore: picker support get first error

This commit is contained in:
Dreamacro 2020-04-16 18:31:40 +08:00
parent 1825535abd
commit 5c03613858
3 changed files with 20 additions and 3 deletions

View file

@ -15,8 +15,10 @@ type Picker struct {
wg sync.WaitGroup wg sync.WaitGroup
once sync.Once once sync.Once
result interface{} errOnce sync.Once
result interface{}
err error
} }
func newPicker(ctx context.Context, cancel func()) *Picker { func newPicker(ctx context.Context, cancel func()) *Picker {
@ -49,6 +51,11 @@ func (p *Picker) Wait() interface{} {
return p.result return p.result
} }
// Error return the first error (if all success return nil)
func (p *Picker) Error() error {
return p.err
}
// Go calls the given function in a new goroutine. // Go calls the given function in a new goroutine.
// The first call to return a nil error cancels the group; its result will be returned by Wait. // The first call to return a nil error cancels the group; its result will be returned by Wait.
func (p *Picker) Go(f func() (interface{}, error)) { func (p *Picker) Go(f func() (interface{}, error)) {
@ -64,6 +71,10 @@ func (p *Picker) Go(f func() (interface{}, error)) {
p.cancel() p.cancel()
} }
}) })
} else {
p.errOnce.Do(func() {
p.err = err
})
} }
}() }()
} }

View file

@ -36,4 +36,5 @@ func TestPicker_Timeout(t *testing.T) {
number := picker.Wait() number := picker.Wait()
assert.Nil(t, number) assert.Nil(t, number)
assert.NotNil(t, picker.Error())
} }

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt"
"math/rand" "math/rand"
"net" "net"
"strings" "strings"
@ -182,7 +183,11 @@ func (r *Resolver) batchExchange(clients []dnsClient, m *D.Msg) (msg *D.Msg, err
elm := fast.Wait() elm := fast.Wait()
if elm == nil { if elm == nil {
return nil, errors.New("All DNS requests failed") err := errors.New("All DNS requests failed")
if fErr := fast.Error(); fErr != nil {
err = fmt.Errorf("%w, first error: %s", err, fErr.Error())
}
return nil, err
} }
msg = elm.(*D.Msg) msg = elm.(*D.Msg)