mirror of https://github.com/grpc/grpc-go.git
Change errors returned by ac.wait()
This commit is contained in:
parent
cd5721c02f
commit
c72b08a774
4
call.go
4
call.go
|
@ -170,9 +170,9 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
|
||||||
if _, ok := err.(*rpcError); ok {
|
if _, ok := err.(*rpcError); ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err == errConnClosing {
|
if err == errConnClosing || err == errConnUnavailable {
|
||||||
if c.failFast {
|
if c.failFast {
|
||||||
return Errorf(codes.Unavailable, "%v", errConnClosing)
|
return Errorf(codes.Unavailable, "%v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,9 @@ var (
|
||||||
errConnDrain = errors.New("grpc: the connection is drained")
|
errConnDrain = errors.New("grpc: the connection is drained")
|
||||||
// errConnClosing indicates that the connection is closing.
|
// errConnClosing indicates that the connection is closing.
|
||||||
errConnClosing = errors.New("grpc: the connection is closing")
|
errConnClosing = errors.New("grpc: the connection is closing")
|
||||||
errNoAddr = errors.New("grpc: there is no address available to dial")
|
// errConnUnavailable indicates that the connection is unavailable.
|
||||||
|
errConnUnavailable = errors.New("grpc: the connection is unavailable")
|
||||||
|
errNoAddr = errors.New("grpc: there is no address available to dial")
|
||||||
// minimum time to give a connection to complete
|
// minimum time to give a connection to complete
|
||||||
minConnectTimeout = 20 * time.Second
|
minConnectTimeout = 20 * time.Second
|
||||||
)
|
)
|
||||||
|
@ -501,11 +503,7 @@ func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions)
|
||||||
}
|
}
|
||||||
return nil, nil, errConnClosing
|
return nil, nil, errConnClosing
|
||||||
}
|
}
|
||||||
// ac.wait should block on transient failure only if balancer is nil and RPC is non-failfast.
|
t, err := ac.wait(ctx, cc.dopts.balancer != nil, !opts.BlockingWait)
|
||||||
// - If RPC is failfast, ac.wait should not block.
|
|
||||||
// - If balancer is not nil, ac.wait should return errConnClosing on transient failure
|
|
||||||
// so that non-failfast RPCs will try to get a new transport instead of waiting on ac.
|
|
||||||
t, err := ac.wait(ctx, cc.dopts.balancer == nil && opts.BlockingWait)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if put != nil {
|
if put != nil {
|
||||||
put()
|
put()
|
||||||
|
@ -757,36 +755,42 @@ func (ac *addrConn) transportMonitor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or
|
// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or
|
||||||
// iv) transport is in TransientFailure and blocking is false.
|
// iv) transport is in TransientFailure and there's no balancer/failfast is true.
|
||||||
func (ac *addrConn) wait(ctx context.Context, blocking bool) (transport.ClientTransport, error) {
|
func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (transport.ClientTransport, error) {
|
||||||
for {
|
for {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
switch {
|
switch {
|
||||||
case ac.state == Shutdown:
|
case ac.state == Shutdown:
|
||||||
err := ac.tearDownErr
|
if failfast || !hasBalancer {
|
||||||
|
// RPC is failfast or balancer is nil. This RPC should fail with ac.tearDownErr.
|
||||||
|
err := ac.tearDownErr
|
||||||
|
ac.mu.Unlock()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
return nil, err
|
return nil, errConnClosing
|
||||||
case ac.state == Ready:
|
case ac.state == Ready:
|
||||||
ct := ac.transport
|
ct := ac.transport
|
||||||
ac.mu.Unlock()
|
ac.mu.Unlock()
|
||||||
return ct, nil
|
return ct, nil
|
||||||
case ac.state == TransientFailure && !blocking:
|
case ac.state == TransientFailure:
|
||||||
ac.mu.Unlock()
|
if failfast || hasBalancer {
|
||||||
return nil, errConnClosing
|
ac.mu.Unlock()
|
||||||
default:
|
return nil, errConnUnavailable
|
||||||
ready := ac.ready
|
|
||||||
if ready == nil {
|
|
||||||
ready = make(chan struct{})
|
|
||||||
ac.ready = ready
|
|
||||||
}
|
|
||||||
ac.mu.Unlock()
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, toRPCErr(ctx.Err())
|
|
||||||
// Wait until the new transport is ready or failed.
|
|
||||||
case <-ready:
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ready := ac.ready
|
||||||
|
if ready == nil {
|
||||||
|
ready = make(chan struct{})
|
||||||
|
ac.ready = ready
|
||||||
|
}
|
||||||
|
ac.mu.Unlock()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, toRPCErr(ctx.Err())
|
||||||
|
// Wait until the new transport is ready or failed.
|
||||||
|
case <-ready:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,9 +146,9 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
|
||||||
if _, ok := err.(*rpcError); ok {
|
if _, ok := err.(*rpcError); ok {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err == errConnClosing {
|
if err == errConnClosing || err == errConnUnavailable {
|
||||||
if c.failFast {
|
if c.failFast {
|
||||||
return nil, Errorf(codes.Unavailable, "%v", errConnClosing)
|
return nil, Errorf(codes.Unavailable, "%v", err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue