use of com.linkedin.r2.message.Response in project rest.li by linkedin.
the class TrackerClientTest method testCallTrackingStreamRequest.
@Test
public void testCallTrackingStreamRequest() throws Exception {
URI uri = URI.create("http://test.qa.com:1234/foo");
SettableClock clock = new SettableClock();
AtomicInteger action = new AtomicInteger(0);
TransportClient tc = new TransportClient() {
@Override
public void restRequest(RestRequest request, RequestContext requestContext, Map<String, String> wireAttrs, TransportCallback<RestResponse> callback) {
}
@Override
public void streamRequest(StreamRequest request, RequestContext requestContext, Map<String, String> wireAttrs, TransportCallback<StreamResponse> callback) {
clock.addDuration(5);
switch(action.get()) {
// success
case 0:
callback.onResponse(TransportResponseImpl.success(new StreamResponseBuilder().build(EntityStreams.emptyStream())));
break;
// fail with stream exception
case 1:
callback.onResponse(TransportResponseImpl.error(new StreamException(new StreamResponseBuilder().setStatus(500).build(EntityStreams.emptyStream()))));
break;
// fail with timeout exception
case 2:
callback.onResponse(TransportResponseImpl.error(new RemoteInvocationException(new TimeoutException())));
break;
// fail with other exception
default:
callback.onResponse(TransportResponseImpl.error(new RuntimeException()));
break;
}
}
@Override
public void shutdown(Callback<None> callback) {
}
};
TrackerClient client = createTrackerClient(tc, clock, uri);
CallTracker callTracker = client.getCallTracker();
CallTracker.CallStats stats;
DegraderControl degraderControl = client.getDegraderControl(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
DelayConsumeCallback delayConsumeCallback = new DelayConsumeCallback();
client.streamRequest(new StreamRequestBuilder(uri).build(EntityStreams.emptyStream()), new RequestContext(), new HashMap<>(), delayConsumeCallback);
clock.addDuration(5);
// we only recorded the time when stream response arrives, but callcompletion.endcall hasn't been called yet.
Assert.assertEquals(callTracker.getCurrentCallCountTotal(), 0);
Assert.assertEquals(callTracker.getCurrentErrorCountTotal(), 0);
// delay
clock.addDuration(100);
delayConsumeCallback.consume();
clock.addDuration(5000);
// now that we consumed the entity stream, callcompletion.endcall has been called.
stats = callTracker.getCallStats();
Assert.assertEquals(stats.getCallCount(), 1);
Assert.assertEquals(stats.getErrorCount(), 0);
Assert.assertEquals(stats.getCallCountTotal(), 1);
Assert.assertEquals(stats.getErrorCountTotal(), 0);
Assert.assertEquals(degraderControl.getCurrentComputedDropRate(), 0.0, 0.001);
action.set(1);
client.streamRequest(new StreamRequestBuilder(uri).build(EntityStreams.emptyStream()), new RequestContext(), new HashMap<>(), delayConsumeCallback);
clock.addDuration(5);
// we endcall with error immediately for stream exception, even before the entity is consumed
Assert.assertEquals(callTracker.getCurrentCallCountTotal(), 2);
Assert.assertEquals(callTracker.getCurrentErrorCountTotal(), 1);
delayConsumeCallback.consume();
clock.addDuration(5000);
// no change in tracking after entity is consumed
stats = callTracker.getCallStats();
Assert.assertEquals(stats.getCallCount(), 1);
Assert.assertEquals(stats.getErrorCount(), 1);
Assert.assertEquals(stats.getCallCountTotal(), 2);
Assert.assertEquals(stats.getErrorCountTotal(), 1);
Assert.assertEquals(degraderControl.getCurrentComputedDropRate(), 0.2, 0.001);
action.set(2);
client.streamRequest(new StreamRequestBuilder(uri).build(EntityStreams.emptyStream()), new RequestContext(), new HashMap<>(), new TestTransportCallback<>());
clock.addDuration(5);
Assert.assertEquals(callTracker.getCurrentCallCountTotal(), 3);
Assert.assertEquals(callTracker.getCurrentErrorCountTotal(), 2);
clock.addDuration(5000);
stats = callTracker.getCallStats();
Assert.assertEquals(stats.getCallCount(), 1);
Assert.assertEquals(stats.getErrorCount(), 1);
Assert.assertEquals(stats.getCallCountTotal(), 3);
Assert.assertEquals(stats.getErrorCountTotal(), 2);
Assert.assertEquals(degraderControl.getCurrentComputedDropRate(), 0.4, 0.001);
action.set(3);
client.streamRequest(new StreamRequestBuilder(uri).build(EntityStreams.emptyStream()), new RequestContext(), new HashMap<>(), new TestTransportCallback<>());
clock.addDuration(5);
Assert.assertEquals(callTracker.getCurrentCallCountTotal(), 4);
Assert.assertEquals(callTracker.getCurrentErrorCountTotal(), 3);
clock.addDuration(5000);
stats = callTracker.getCallStats();
Assert.assertEquals(stats.getCallCount(), 1);
Assert.assertEquals(stats.getErrorCount(), 1);
Assert.assertEquals(stats.getCallCountTotal(), 4);
Assert.assertEquals(stats.getErrorCountTotal(), 3);
Assert.assertEquals(degraderControl.getCurrentComputedDropRate(), 0.2, 0.001);
}
use of com.linkedin.r2.message.Response in project rest.li by linkedin.
the class RAPResponseHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, RestResponse response) throws Exception {
final Map<String, String> headers = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
final Map<String, String> wireAttrs = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
headers.putAll(response.getHeaders());
wireAttrs.putAll(WireAttributeHelper.removeWireAttributes(headers));
final RestResponse newResponse = new RestResponseBuilder(response).unsafeSetHeaders(headers).build();
// In general there should always be a callback to handle a received message,
// but it could have been removed due to a previous exception or closure on the
// channel
TransportCallback<RestResponse> callback = ctx.channel().attr(CALLBACK_ATTR_KEY).getAndRemove();
if (callback != null) {
LOG.debug("{}: handling a response", ctx.channel().remoteAddress());
callback.onResponse(TransportResponseImpl.success(newResponse, wireAttrs));
} else {
LOG.debug("{}: dropped a response", ctx.channel().remoteAddress());
}
ctx.fireChannelRead(response);
}
use of com.linkedin.r2.message.Response in project rest.li by linkedin.
the class RAPStreamResponseHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, StreamResponse response) throws Exception {
final Map<String, String> headers = new HashMap<String, String>(response.getHeaders());
final Map<String, String> wireAttrs = new HashMap<String, String>(WireAttributeHelper.removeWireAttributes(headers));
final StreamResponse newResponse = new StreamResponseBuilder(response).unsafeSetHeaders(headers).build(response.getEntityStream());
// In general there should always be a callback to handle a received message,
// but it could have been removed due to a previous exception or closure on the
// channel
TransportCallback<StreamResponse> callback = ctx.channel().attr(CALLBACK_ATTR_KEY).getAndRemove();
if (callback != null) {
LOG.debug("{}: handling a response", ctx.channel().remoteAddress());
callback.onResponse(TransportResponseImpl.success(newResponse, wireAttrs));
} else {
LOG.debug("{}: dropped a response", ctx.channel().remoteAddress());
}
}
use of com.linkedin.r2.message.Response in project rest.li by linkedin.
the class StreamExecutionCallback method onResponse.
@Override
public void onResponse(TransportResponse<StreamResponse> response) {
final TransportCallback<StreamResponse> callback = _callbackRef.getAndSet(null);
if (callback != null) {
final TransportResponse<StreamResponse> wrappedResponse;
if (response.hasError()) {
wrappedResponse = response;
} else {
EventLoopConnector connector = new EventLoopConnector(response.getResponse().getEntityStream());
StreamResponse newResponse = response.getResponse().builder().build(EntityStreams.newEntityStream(connector));
wrappedResponse = TransportResponseImpl.success(newResponse, response.getWireAttributes());
}
trySchedule(() -> callback.onResponse(wrappedResponse));
} else {
LOG.warn("Received response {} while _callback is null. Ignored.", response.getResponse());
}
}
use of com.linkedin.r2.message.Response in project rest.li by linkedin.
the class TestChannelPoolHandler method testConnectionClose.
@Test(dataProvider = "connectionClose")
public void testConnectionClose(String headerName, String headerValue) {
EmbeddedChannel ch = new EmbeddedChannel(new ChannelPoolHandler());
FakePool pool = new FakePool();
ch.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
RestResponse response = new RestResponseBuilder().setHeader(headerName, headerValue).build();
ch.writeInbound(response);
Assert.assertTrue(pool.isDisposeCalled());
Assert.assertFalse(pool.isPutCalled());
}
Aggregations