protected void asyncErrorCallback(ChannelHandlerContext ctx, Throwable error) { executeOnlyIfChannelIsActive( ctx, "NonblockingEndpointExecutionHandler-asyncErrorCallback", () -> ctx.fireExceptionCaught(error) ); } }
protected void asyncErrorCallback(ChannelHandlerContext ctx, Throwable error) { executeOnlyIfChannelIsActive( ctx, "NonblockingEndpointExecutionHandler-asyncErrorCallback", () -> ctx.fireExceptionCaught(error) ); } }
executeOnlyIfChannelIsActive(ctx, "StreamingCallbackForCtx-unrecoverableErrorOccurred", () -> { Pair<Deque<Span>, Map<String, String>> originalThreadInfo = null; try {
executeOnlyIfChannelIsActive(ctx, "StreamingCallbackForCtx-unrecoverableErrorOccurred", () -> { Pair<Deque<Span>, Map<String, String>> originalThreadInfo = null; try {
@DataProvider(value = { "true", "false" }) @Test public void executeOnlyIfChannelIsActive_executes_the_runnable_depending_on_whether_the_channel_is_active( boolean channelActive ) { // given doReturn(channelActive).when(channelMock).isActive(); // when AsyncNettyHelper.executeOnlyIfChannelIsActive(ctxMock, "foo", runnableMock); // then if (channelActive) verify(runnableMock).run(); else verifyZeroInteractions(runnableMock); }
protected void asyncCallback(ChannelHandlerContext ctx, ResponseInfo<?> responseInfo) { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get(); if (responseInfo.isChunkedResponse()) { // Whoops, chunked responses are not allowed for this endpoint type. asyncErrorCallback( ctx, new Exception("NonblockingEndpoint execution resulted in a chunked ResponseInfo, when only full " + "ResponseInfos are allowed. offending_endpoint_class=" + state.getEndpointForExecution().getClass().getName()) ); } else { executeOnlyIfChannelIsActive( ctx, "NonblockingEndpointExecutionHandler-asyncCallback", () -> { // We have to set the ResponseInfo on the state and fire the event while in the // channel's EventLoop. Otherwise there could be a race condition with an error // that was fired down the pipe that sets the ResponseInfo on the state first, then // this comes along and replaces the ResponseInfo (or vice versa). EventExecutor executor = ctx.executor(); if (executor.inEventLoop()) { setResponseInfoAndActivatePipelineForResponse(state, responseInfo, ctx); } else { executor.execute(() -> setResponseInfoAndActivatePipelineForResponse(state, responseInfo, ctx)); } } ); } }
protected void asyncCallback(ChannelHandlerContext ctx, ResponseInfo<?> responseInfo) { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get(); if (responseInfo.isChunkedResponse()) { // Whoops, chunked responses are not allowed for this endpoint type. asyncErrorCallback( ctx, new Exception("NonblockingEndpoint execution resulted in a chunked ResponseInfo, when only full " + "ResponseInfos are allowed. offending_endpoint_class=" + state.getEndpointForExecution().getClass().getName()) ); } else { executeOnlyIfChannelIsActive( ctx, "NonblockingEndpointExecutionHandler-asyncCallback", () -> { // We have to set the ResponseInfo on the state and fire the event while in the // channel's EventLoop. Otherwise there could be a race condition with an error // that was fired down the pipe that sets the ResponseInfo on the state first, then // this comes along and replaces the ResponseInfo (or vice versa). EventExecutor executor = ctx.executor(); if (executor.inEventLoop()) { setResponseInfoAndActivatePipelineForResponse(state, responseInfo, ctx); } else { executor.execute(() -> setResponseInfoAndActivatePipelineForResponse(state, responseInfo, ctx)); } } ); } }
channelIsActive = executeOnlyIfChannelIsActive(ctx, "StreamingCallbackForCtx-messageReceived", () -> { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
channelIsActive = executeOnlyIfChannelIsActive(ctx, "StreamingCallbackForCtx-messageReceived", () -> { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
ctx ).run(); executeOnlyIfChannelIsActive( ctx, "ProxyRouterEndpointExecutionHandler-streamchunk-writefuture-unsuccessful", ctx ).run(); executeOnlyIfChannelIsActive( ctx, "ProxyRouterEndpointExecutionHandler-streamchunk-unsuccessful", () -> ctx.fireExceptionCaught(errorToFire)
ctx ).run(); executeOnlyIfChannelIsActive( ctx, "ProxyRouterEndpointExecutionHandler-streamchunk-writefuture-unsuccessful", ctx ).run(); executeOnlyIfChannelIsActive( ctx, "ProxyRouterEndpointExecutionHandler-streamchunk-unsuccessful", () -> ctx.fireExceptionCaught(errorToFire)
@Test public void executeOnlyIfChannelIsActive_sets_original_tracing_and_mdc_info_back_even_if_channel_not_active_and_exception_occurs() { // given setupStateWithTracingAndMdcInfo(); doReturn(false).when(channelMock).isActive(); RuntimeException exToThrow = new RuntimeException("kaboom"); doThrow(exToThrow).when(requestInfoMock).releaseAllResources(); resetTracingAndMdc(); Tracer.getInstance().startRequestWithRootSpan("foo-" + UUID.randomUUID().toString()); Pair<Deque<Span>, Map<String, String>> preCallTracingInfo = Pair.of( Tracer.getInstance().getCurrentSpanStackCopy(), MDC.getCopyOfContextMap() ); // when Throwable ex = catchThrowable(() -> AsyncNettyHelper.executeOnlyIfChannelIsActive(ctxMock, "foo", runnableMock)); // then verify(requestInfoMock).releaseAllResources(); assertThat(ex).isSameAs(exToThrow); Pair<Deque<Span>, Map<String, String>> postCallTracingInfo = Pair.of( Tracer.getInstance().getCurrentSpanStackCopy(), MDC.getCopyOfContextMap() ); assertThat(postCallTracingInfo).isEqualTo(preCallTracingInfo); }
AsyncNettyHelper.executeOnlyIfChannelIsActive(ctxMock, "foo", runnableMock);