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);
}
}
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));
}
Aggregations