Fix: use the fastest whether the result is successful
This commit is contained in:
@ -17,15 +17,12 @@ type Picker struct {
|
||||
|
||||
once sync.Once
|
||||
result interface{}
|
||||
|
||||
firstDone chan struct{}
|
||||
}
|
||||
|
||||
func newPicker(ctx context.Context, cancel func()) *Picker {
|
||||
return &Picker{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
firstDone: make(chan struct{}, 1),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,12 +39,6 @@ func WithTimeout(ctx context.Context, timeout time.Duration) (*Picker, context.C
|
||||
return newPicker(ctx, cancel), ctx
|
||||
}
|
||||
|
||||
// WithoutAutoCancel returns a new Picker and an associated Context derived from ctx,
|
||||
// but it wouldn't cancel context when the first element return.
|
||||
func WithoutAutoCancel(ctx context.Context) *Picker {
|
||||
return newPicker(ctx, nil)
|
||||
}
|
||||
|
||||
// Wait blocks until all function calls from the Go method have returned,
|
||||
// then returns the first nil error result (if any) from them.
|
||||
func (p *Picker) Wait() interface{} {
|
||||
@ -58,17 +49,6 @@ func (p *Picker) Wait() interface{} {
|
||||
return p.result
|
||||
}
|
||||
|
||||
// WaitWithoutCancel blocks until the first result return, if timeout will return nil.
|
||||
// The return of this function will not wait for the cancel of context.
|
||||
func (p *Picker) WaitWithoutCancel() interface{} {
|
||||
select {
|
||||
case <-p.firstDone:
|
||||
return p.result
|
||||
case <-p.ctx.Done():
|
||||
return p.result
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (p *Picker) Go(f func() (interface{}, error)) {
|
||||
@ -80,7 +60,6 @@ func (p *Picker) Go(f func() (interface{}, error)) {
|
||||
if ret, err := f(); err == nil {
|
||||
p.once.Do(func() {
|
||||
p.result = ret
|
||||
p.firstDone <- struct{}{}
|
||||
if p.cancel != nil {
|
||||
p.cancel()
|
||||
}
|
||||
|
@ -37,30 +37,3 @@ func TestPicker_Timeout(t *testing.T) {
|
||||
number := picker.Wait()
|
||||
assert.Nil(t, number)
|
||||
}
|
||||
|
||||
func TestPicker_WaitWithoutAutoCancel(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*60)
|
||||
defer cancel()
|
||||
picker := WithoutAutoCancel(ctx)
|
||||
|
||||
trigger := false
|
||||
picker.Go(sleepAndSend(ctx, 10, 1))
|
||||
picker.Go(func() (interface{}, error) {
|
||||
timer := time.NewTimer(time.Millisecond * time.Duration(30))
|
||||
select {
|
||||
case <-timer.C:
|
||||
trigger = true
|
||||
return 2, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
})
|
||||
elm := picker.WaitWithoutCancel()
|
||||
|
||||
assert.NotNil(t, elm)
|
||||
assert.Equal(t, elm.(int), 1)
|
||||
|
||||
elm = picker.Wait()
|
||||
assert.True(t, trigger)
|
||||
assert.Equal(t, elm.(int), 1)
|
||||
}
|
||||
|
Reference in New Issue
Block a user