use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.
the class Http2NettyStreamClient method doWriteRequestWithWireAttrHeaders.
@Override
protected void doWriteRequestWithWireAttrHeaders(Request request, final RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, TimeoutTransportCallback<StreamResponse> callback, long requestTimeout) {
final AsyncPool<Channel> pool;
try {
pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
} catch (IllegalStateException e) {
errorResponse(callback, e);
return;
}
requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_2);
Callback<Channel> getCallback = new ChannelPoolGetCallback(pool, request, requestContext, callback, requestTimeout);
final Cancellable pendingGet = pool.get(getCallback);
if (pendingGet != null) {
callback.addTimeoutTask(pendingGet::cancel);
}
}
use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.
the class HttpNettyClient method doWriteRequest.
@Override
protected void doWriteRequest(RestRequest request, RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, final TimeoutTransportCallback<RestResponse> callback, long requestTimeout) {
final RestRequest newRequest = new RestRequestBuilder(request).overwriteHeaders(WireAttributeHelper.toWireAttributes(wireAttrs)).build();
requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
final AsyncPool<Channel> pool;
try {
pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
} catch (IllegalStateException e) {
errorResponse(callback, e);
return;
}
final Cancellable pendingGet = pool.get(new Callback<Channel>() {
@Override
public void onSuccess(final Channel channel) {
// This handler ensures the channel is returned to the pool at the end of the
// Netty pipeline.
channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
callback.addTimeoutTask(() -> {
AsyncPool<Channel> pool1 = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndSet(null);
if (pool1 != null) {
pool1.dispose(channel);
}
});
TransportCallback<RestResponse> sslTimingCallback = SslHandshakeTimingHandler.getSslTimingCallback(channel, requestContext, callback);
// This handler invokes the callback with the response once it arrives.
channel.attr(RAPResponseHandler.CALLBACK_ATTR_KEY).set(sslTimingCallback);
// Set the session validator requested by the user
SslSessionValidator sslSessionValidator = (SslSessionValidator) requestContext.getLocalAttr(R2Constants.REQUESTED_SSL_SESSION_VALIDATOR);
channel.attr(NettyChannelAttributes.SSL_SESSION_VALIDATOR).set(sslSessionValidator);
final NettyClientState state = _state.get();
if (state == NettyClientState.REQUESTS_STOPPING || state == NettyClientState.SHUTDOWN) {
// In this case, we acquired a channel from the pool as request processing is halting.
// The shutdown task might not timeout this callback, since it may already have scanned
// all the channels for pending requests before we set the callback as the channel
// attachment. The TimeoutTransportCallback ensures the user callback in never
// invoked more than once, so it is safe to invoke it unconditionally.
errorResponse(sslTimingCallback, new TimeoutException("Operation did not complete before shutdown"));
// The channel is usually release in two places: timeout or in the netty pipeline.
// Since we call the callback above, the timeout associated will be never invoked. On top of that
// we never send the request to the pipeline (due to the return statement), and nobody is releasing the channel
// until the channel is forcefully closed by the shutdownTimeout. Therefore we have to release it here
AsyncPool<Channel> pool = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndSet(null);
if (pool != null) {
pool.put(channel);
}
return;
}
// here we want the exception in outbound operations to be passed back through pipeline so that
// the user callback would be invoked with the exception and the channel can be put back into the pool
channel.writeAndFlush(newRequest).addListener(new ErrorChannelFutureListener());
}
@Override
public void onError(Throwable e) {
errorResponse(callback, e);
}
});
if (pendingGet != null) {
callback.addTimeoutTask(pendingGet::cancel);
}
}
use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.
the class TestChannelPoolManager method test.
@Test
public void test() {
ChannelPoolFactory factory = new ChannelPoolFactory() {
@Override
public AsyncPool<Channel> getPool(SocketAddress address) {
return new FakePool<>();
}
};
ChannelPoolManager m = new ChannelPoolManagerImpl(factory, null, null);
final int NUM = 100;
List<SocketAddress> addresses = new ArrayList<>(NUM);
for (int i = 0; i < NUM; i++) {
addresses.add(new InetSocketAddress(i));
}
List<AsyncPool<Channel>> pools = new ArrayList<>(NUM);
for (int i = 0; i < NUM; i++) {
pools.add(m.getPoolForAddress(addresses.get(i)));
}
for (int i = 0; i < NUM; i++) {
Assert.assertEquals(m.getPoolForAddress(addresses.get(i)), pools.get(i));
}
}
use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.
the class HttpNettyStreamClient method doWriteRequestWithWireAttrHeaders.
@Override
protected void doWriteRequestWithWireAttrHeaders(Request request, RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, TimeoutTransportCallback<StreamResponse> callback, long requestTimeout) {
final AsyncPool<Channel> pool;
try {
pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
} catch (IllegalStateException e) {
errorResponse(callback, e);
return;
}
requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
Callback<Channel> getCallback = new ChannelPoolGetCallback(pool, request, requestContext, callback, requestTimeout);
final Cancellable pendingGet = pool.get(getCallback);
if (pendingGet != null) {
callback.addTimeoutTask(pendingGet::cancel);
}
}
use of com.linkedin.r2.transport.http.client.AsyncPool in project rest.li by linkedin.
the class HttpNettyClient method writeRequest.
private void writeRequest(RestRequest request, RequestContext requestContext, Map<String, String> wireAttrs, final TimeoutTransportCallback<RestResponse> callback) {
State state = _state.get();
if (state != State.RUNNING) {
errorResponse(callback, new IllegalStateException("Client is " + state));
return;
}
URI uri = request.getURI();
String scheme = uri.getScheme();
if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
errorResponse(callback, new IllegalArgumentException("Unknown scheme: " + scheme + " (only http/https is supported)"));
return;
}
String host = uri.getHost();
int port = uri.getPort();
if (port == -1) {
port = "http".equalsIgnoreCase(scheme) ? HTTP_DEFAULT_PORT : HTTPS_DEFAULT_PORT;
}
final RestRequest newRequest = new RestRequestBuilder(request).overwriteHeaders(WireAttributeHelper.toWireAttributes(wireAttrs)).build();
final SocketAddress address;
try {
// TODO investigate DNS resolution and timing
InetAddress inetAddress = InetAddress.getByName(host);
address = new InetSocketAddress(inetAddress, port);
requestContext.putLocalAttr(R2Constants.REMOTE_SERVER_ADDR, inetAddress.getHostAddress());
} catch (UnknownHostException e) {
errorResponse(callback, e);
return;
}
requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
final AsyncPool<Channel> pool;
try {
pool = _channelPoolManager.getPoolForAddress(address);
} catch (IllegalStateException e) {
errorResponse(callback, e);
return;
}
final Cancellable pendingGet = pool.get(new Callback<Channel>() {
@Override
public void onSuccess(final Channel channel) {
// This handler ensures the channel is returned to the pool at the end of the
// Netty pipeline.
channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
callback.addTimeoutTask(new Runnable() {
@Override
public void run() {
AsyncPool<Channel> pool = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndRemove();
if (pool != null) {
pool.dispose(channel);
}
}
});
// This handler invokes the callback with the response once it arrives.
channel.attr(RAPResponseHandler.CALLBACK_ATTR_KEY).set(callback);
final State state = _state.get();
if (state == State.REQUESTS_STOPPING || state == State.SHUTDOWN) {
// In this case, we acquired a channel from the pool as request processing is halting.
// The shutdown task might not timeout this callback, since it may already have scanned
// all the channels for pending requests before we set the callback as the channel
// attachment. The TimeoutTransportCallback ensures the user callback in never
// invoked more than once, so it is safe to invoke it unconditionally.
errorResponse(callback, new TimeoutException("Operation did not complete before shutdown"));
return;
}
// here we want the exception in outbound operations to be passed back through pipeline so that
// the user callback would be invoked with the exception and the channel can be put back into the pool
channel.writeAndFlush(newRequest).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
@Override
public void onError(Throwable e) {
errorResponse(callback, e);
}
});
if (pendingGet != null) {
callback.addTimeoutTask(new Runnable() {
@Override
public void run() {
pendingGet.cancel();
}
});
}
}
Aggregations