@Test public void cancelInOnMessageShouldInvokeStreamCancel() throws Exception { final ClientCallImpl<Void, Void> call = new ClientCallImpl<Void, Void>( DESCRIPTOR, MoreExecutors.directExecutor(), CallOptions.DEFAULT, provider, deadlineCancellationExecutor); final Exception cause = new Exception(); ClientCall.Listener<Void> callListener = new ClientCall.Listener<Void>() { @Override public void onMessage(Void message) { call.cancel("foo", cause); } }; call.start(callListener, new Metadata()); call.halfClose(); call.request(1); verify(stream).start(listenerArgumentCaptor.capture()); ClientStreamListener streamListener = listenerArgumentCaptor.getValue(); streamListener.onReady(); streamListener.headersRead(new Metadata()); streamListener.messageRead(new ByteArrayInputStream(new byte[0])); verify(stream).cancel(statusCaptor.capture()); Status status = statusCaptor.getValue(); assertEquals(Status.CANCELLED.getCode(), status.getCode()); assertEquals("foo", status.getDescription()); assertSame(cause, status.getCause()); }
private static <ReqT, RespT, OutputT> OutputT getBlockingResult( AbstractRetryingRpcListener<ReqT, RespT, OutputT> listener) { try { listener.start(); return listener.getCompletionFuture().get(); } catch (InterruptedException e) { listener.cancel(); throw Status.CANCELLED.withCause(e).asRuntimeException(); } catch (ExecutionException e) { listener.cancel(); throw Status.fromThrowable(e).asRuntimeException(); } }
@Override public void sendMessage(ReqT message) { Preconditions.checkState(stream != null, "Not started"); Preconditions.checkState(!cancelCalled, "call was cancelled"); Preconditions.checkState(!halfCloseCalled, "call was half-closed"); try { // TODO(notcarl): Find out if messageIs needs to be closed. InputStream messageIs = method.streamRequest(message); stream.writeMessage(messageIs); } catch (Throwable e) { stream.cancel(Status.CANCELLED.withCause(e).withDescription("Failed to stream message")); return; } // For unary requests, we don't flush since we know that halfClose should be coming soon. This // allows us to piggy-back the END_STREAM=true on the last message frame without opening the // possibility of broken applications forgetting to call halfClose without noticing. if (!unaryRequest) { stream.flush(); } }
@Test public void streamCancelAbortsDeadlineTimer() { fakeClock.forwardTime(System.nanoTime(), TimeUnit.NANOSECONDS); ClientCallImpl<Void, Void> call = new ClientCallImpl<Void, Void>( DESCRIPTOR, MoreExecutors.directExecutor(), CallOptions.DEFAULT.withDeadline(Deadline.after(1000, TimeUnit.MILLISECONDS)), provider, deadlineCancellationExecutor); call.start(callListener, new Metadata()); call.cancel("canceled", null); // Run the deadline timer, which should have been cancelled by the previous call to cancel() fakeClock.forwardMillis(1001); verify(stream, times(1)).cancel(statusCaptor.capture()); assertEquals(Status.CANCELLED.getCode(), statusCaptor.getValue().getCode()); }