Search in sources :

Example 1 with RpcProgress

use of io.grpc.internal.ClientStreamListener.RpcProgress in project grpc-java by grpc.

the class NettyClientHandler method goingAway.

/**
 * Handler for a GOAWAY being received. Fails any streams created after the
 * last known stream. May only be called during a read.
 */
private void goingAway(long errorCode, byte[] debugData) {
    Status finalStatus = statusFromH2Error(Status.Code.UNAVAILABLE, "GOAWAY shut down transport", errorCode, debugData);
    lifecycleManager.notifyGracefulShutdown(finalStatus);
    abruptGoAwayStatus = statusFromH2Error(Status.Code.UNAVAILABLE, "Abrupt GOAWAY closed unsent stream", errorCode, debugData);
    // While this _should_ be UNAVAILABLE, Netty uses the wrong stream id in the GOAWAY when it
    // fails streams due to HPACK failures (e.g., header list too large). To be more conservative,
    // we assume any sent streams may be related to the GOAWAY. This should rarely impact users
    // since the main time servers should use abrupt GOAWAYs is if there is a protocol error, and if
    // there wasn't a protocol error the error code was probably NO_ERROR which is mapped to
    // UNAVAILABLE. https://github.com/netty/netty/issues/10670
    final Status abruptGoAwayStatusConservative = statusFromH2Error(null, "Abrupt GOAWAY closed sent stream", errorCode, debugData);
    final boolean mayBeHittingNettyBug = errorCode != Http2Error.NO_ERROR.code();
    // Try to allocate as many in-flight streams as possible, to reduce race window of
    // https://github.com/grpc/grpc-java/issues/2562 . To be of any help, the server has to
    // gracefully shut down the connection with two GOAWAYs. gRPC servers generally send a PING
    // after the first GOAWAY, so they can very precisely detect when the GOAWAY has been
    // processed and thus this processing must be in-line before processing additional reads.
    // This can cause reentrancy, but should be minor since it is normal to handle writes in
    // response to a read. Also, the call stack is rather shallow at this point
    clientWriteQueue.drainNow();
    if (lifecycleManager.notifyShutdown(finalStatus)) {
        // This is for the only RPCs that are actually covered by the GOAWAY error code. All other
        // RPCs were not observed by the remote and so should be UNAVAILABLE.
        channelInactiveReason = statusFromH2Error(null, "Connection closed after GOAWAY", errorCode, debugData);
    }
    final int lastKnownStream = connection().local().lastStreamKnownByPeer();
    try {
        connection().forEachActiveStream(new Http2StreamVisitor() {

            @Override
            public boolean visit(Http2Stream stream) throws Http2Exception {
                if (stream.id() > lastKnownStream) {
                    NettyClientStream.TransportState clientStream = clientStream(stream);
                    if (clientStream != null) {
                        // RpcProgress _should_ be REFUSED, but are being conservative. See comment for
                        // abruptGoAwayStatusConservative. This does reduce our ability to perform transparent
                        // retries, but only if something else caused a connection failure.
                        RpcProgress progress = mayBeHittingNettyBug ? RpcProgress.PROCESSED : RpcProgress.REFUSED;
                        clientStream.transportReportStatus(abruptGoAwayStatusConservative, progress, false, new Metadata());
                    }
                    stream.close();
                }
                return true;
            }
        });
    } catch (Http2Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : Status(io.grpc.Status) Http2Exception(io.netty.handler.codec.http2.Http2Exception) Http2StreamVisitor(io.netty.handler.codec.http2.Http2StreamVisitor) Metadata(io.grpc.Metadata) RpcProgress(io.grpc.internal.ClientStreamListener.RpcProgress) Http2Stream(io.netty.handler.codec.http2.Http2Stream)

Example 2 with RpcProgress

use of io.grpc.internal.ClientStreamListener.RpcProgress in project grpc-java by grpc.

the class FailingClientTransportTest method newStreamStart.

@Test
public void newStreamStart() {
    Status error = Status.UNAVAILABLE;
    RpcProgress rpcProgress = RpcProgress.DROPPED;
    FailingClientTransport transport = new FailingClientTransport(error, rpcProgress);
    ClientStream stream = transport.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT, new ClientStreamTracer[] { new ClientStreamTracer() {
    } });
    ClientStreamListener listener = mock(ClientStreamListener.class);
    stream.start(listener);
    verify(listener).closed(eq(error), eq(rpcProgress), any(Metadata.class));
}
Also used : Status(io.grpc.Status) ClientStreamTracer(io.grpc.ClientStreamTracer) Metadata(io.grpc.Metadata) RpcProgress(io.grpc.internal.ClientStreamListener.RpcProgress) Test(org.junit.Test)

Aggregations

Metadata (io.grpc.Metadata)2 Status (io.grpc.Status)2 RpcProgress (io.grpc.internal.ClientStreamListener.RpcProgress)2 ClientStreamTracer (io.grpc.ClientStreamTracer)1 Http2Exception (io.netty.handler.codec.http2.Http2Exception)1 Http2Stream (io.netty.handler.codec.http2.Http2Stream)1 Http2StreamVisitor (io.netty.handler.codec.http2.Http2StreamVisitor)1 Test (org.junit.Test)1