diff --git a/cmd/Godeps/Godeps.json b/cmd/Godeps/Godeps.json index eb1a86a25..6e7b5c850 100644 --- a/cmd/Godeps/Godeps.json +++ b/cmd/Godeps/Godeps.json @@ -237,48 +237,48 @@ }, { "ImportPath": "google.golang.org/grpc", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/codes", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/credentials", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/grpclog", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/internal", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/metadata", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/naming", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/peer", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "google.golang.org/grpc/transport", - "Comment": "v1.0.0-174-gc278196", - "Rev": "c2781963b3af261a37e0f14fdcb7c1fa13259e1f" + "Comment": "v1.0.0-183-g231b4cf", + "Rev": "231b4cfea0e79843053a33f5fe90bd4d84b23cd3" }, { "ImportPath": "gopkg.in/cheggaaa/pb.v1", diff --git a/cmd/vendor/google.golang.org/grpc/call.go b/cmd/vendor/google.golang.org/grpc/call.go index 5fba11eb0..fea07998d 100644 --- a/cmd/vendor/google.golang.org/grpc/call.go +++ b/cmd/vendor/google.golang.org/grpc/call.go @@ -170,9 +170,9 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli if _, ok := err.(*rpcError); ok { return err } - if err == errConnClosing { + if err == errConnClosing || err == errConnUnavailable { if c.failFast { - return Errorf(codes.Unavailable, "%v", errConnClosing) + return Errorf(codes.Unavailable, "%v", err) } continue } diff --git a/cmd/vendor/google.golang.org/grpc/clientconn.go b/cmd/vendor/google.golang.org/grpc/clientconn.go index d16ea2016..27e74e6f2 100644 --- a/cmd/vendor/google.golang.org/grpc/clientconn.go +++ b/cmd/vendor/google.golang.org/grpc/clientconn.go @@ -73,7 +73,9 @@ var ( errConnDrain = errors.New("grpc: the connection is drained") // errConnClosing indicates that 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 minConnectTimeout = 20 * time.Second ) @@ -213,9 +215,14 @@ func WithUserAgent(s string) DialOption { } } -// Dial creates a client connection the given target. +// Dial creates a client connection to the given target. func Dial(target string, opts ...DialOption) (*ClientConn, error) { - ctx := context.Background() + return DialContext(context.Background(), target, opts...) +} + +// DialContext creates a client connection to the given target +// using the supplied context. +func DialContext(ctx context.Context, target string, opts ...DialOption) (*ClientConn, error) { cc := &ClientConn{ target: target, conns: make(map[Address]*addrConn), @@ -472,6 +479,10 @@ func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) if cc.dopts.balancer == nil { // If balancer is nil, there should be only one addrConn available. cc.mu.RLock() + if cc.conns == nil { + cc.mu.RUnlock() + return nil, nil, toRPCErr(ErrClientConnClosing) + } for _, ac = range cc.conns { // Break after the first iteration to get the first addrConn. ok = true @@ -501,11 +512,7 @@ func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) } return nil, nil, errConnClosing } - // ac.wait should block on transient failure only if balancer is nil and RPC is non-failfast. - // - 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) + t, err := ac.wait(ctx, cc.dopts.balancer != nil, !opts.BlockingWait) if err != nil { if put != nil { put() @@ -757,36 +764,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 -// iv) transport is in TransientFailure and blocking is false. -func (ac *addrConn) wait(ctx context.Context, blocking bool) (transport.ClientTransport, error) { +// iv) transport is in TransientFailure and there's no balancer/failfast is true. +func (ac *addrConn) wait(ctx context.Context, hasBalancer, failfast bool) (transport.ClientTransport, error) { for { ac.mu.Lock() switch { 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() - return nil, err + return nil, errConnClosing case ac.state == Ready: ct := ac.transport ac.mu.Unlock() return ct, nil - case ac.state == TransientFailure && !blocking: - ac.mu.Unlock() - return nil, errConnClosing - default: - 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: + case ac.state == TransientFailure: + if failfast || hasBalancer { + ac.mu.Unlock() + 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: + } } } diff --git a/cmd/vendor/google.golang.org/grpc/stream.go b/cmd/vendor/google.golang.org/grpc/stream.go index c1b07e89e..51df3f01d 100644 --- a/cmd/vendor/google.golang.org/grpc/stream.go +++ b/cmd/vendor/google.golang.org/grpc/stream.go @@ -146,9 +146,9 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth if _, ok := err.(*rpcError); ok { return nil, err } - if err == errConnClosing { + if err == errConnClosing || err == errConnUnavailable { if c.failFast { - return nil, Errorf(codes.Unavailable, "%v", errConnClosing) + return nil, Errorf(codes.Unavailable, "%v", err) } continue }