use of io.netty.util.concurrent.PromiseCombiner in project pravega by pravega.
the class ClientConnectionInboundHandler method sendAsync.
@Override
public void sendAsync(List<Append> appends, CompletedCallback callback) {
recentMessage.set(true);
Channel ch;
try {
ch = getChannel();
} catch (ConnectionFailedException e) {
callback.complete(new ConnectionFailedException("Connection to " + connectionName + " is not established."));
return;
}
PromiseCombiner combiner = new PromiseCombiner();
for (Append append : appends) {
batchSizeTracker.recordAppend(append.getEventNumber(), append.getData().readableBytes());
combiner.add(ch.write(append));
}
ch.flush();
ChannelPromise promise = ch.newPromise();
promise.addListener(new GenericFutureListener<Future<? super Void>>() {
@Override
public void operationComplete(Future<? super Void> future) throws Exception {
Throwable cause = future.cause();
callback.complete(cause == null ? null : new ConnectionFailedException(cause));
}
});
combiner.finish(promise);
}
use of io.netty.util.concurrent.PromiseCombiner in project netty by netty.
the class PendingWriteQueue method removeAndWriteAll.
/**
* Remove all pending write operation and performs them via
* {@link ChannelHandlerContext#write(Object, ChannelPromise)}.
*
* @return {@link ChannelFuture} if something was written and {@code null}
* if the {@link PendingWriteQueue} is empty.
*/
public ChannelFuture removeAndWriteAll() {
assert executor.inEventLoop();
if (isEmpty()) {
return null;
}
ChannelPromise p = invoker.newPromise();
PromiseCombiner combiner = new PromiseCombiner(executor);
try {
// will "revive" the queue, so we need to write them up until the queue is empty.
for (PendingWrite write = head; write != null; write = head) {
head = tail = null;
size = 0;
bytes = 0;
while (write != null) {
PendingWrite next = write.next;
Object msg = write.msg;
ChannelPromise promise = write.promise;
recycle(write, false);
if (!(promise instanceof VoidChannelPromise)) {
combiner.add(promise);
}
invoker.write(msg, promise);
write = next;
}
}
combiner.finish(p);
} catch (Throwable cause) {
p.setFailure(cause);
}
assertEmpty();
return p;
}
use of io.netty.util.concurrent.PromiseCombiner in project netty by netty.
the class MessageToMessageEncoder method writePromiseCombiner.
private static void writePromiseCombiner(ChannelHandlerContext ctx, CodecOutputList out, ChannelPromise promise) {
final PromiseCombiner combiner = new PromiseCombiner(ctx.executor());
for (int i = 0; i < out.size(); i++) {
combiner.add(ctx.write(out.getUnsafe(i)));
}
combiner.finish(promise);
}
use of io.netty.util.concurrent.PromiseCombiner in project zuul by Netflix.
the class ClientConnectionsShutdown method gracefullyShutdownClientChannels.
/**
* Note this blocks until all the channels have finished closing.
*/
public void gracefullyShutdownClientChannels() {
LOG.warn("Gracefully shutting down all client channels");
try {
// Mark all active connections to be closed after next response sent.
LOG.warn("Flagging CLOSE_AFTER_RESPONSE on " + channels.size() + " client channels.");
// Pick some arbitrary executor.
PromiseCombiner closeAfterPromises = new PromiseCombiner(ImmediateEventExecutor.INSTANCE);
for (Channel channel : channels) {
ConnectionCloseType.setForChannel(channel, ConnectionCloseType.DELAYED_GRACEFUL);
ChannelPromise closePromise = channel.pipeline().newPromise();
channel.attr(ConnectionCloseChannelAttributes.CLOSE_AFTER_RESPONSE).set(closePromise);
// TODO(carl-mastrangelo): remove closePromise, since I don't think it's needed. Need to verify.
closeAfterPromises.add(channel.closeFuture());
}
// Wait for all of the attempts to close connections gracefully, or max of 30 secs each.
Promise<Void> combinedCloseAfterPromise = executor.newPromise();
closeAfterPromises.finish(combinedCloseAfterPromise);
combinedCloseAfterPromise.await(30, TimeUnit.SECONDS);
// Close all of the remaining active connections.
LOG.warn("Closing remaining active client channels.");
List<ChannelFuture> forceCloseFutures = new ArrayList<>();
channels.forEach(channel -> {
if (channel.isActive()) {
ChannelFuture f = channel.pipeline().close();
forceCloseFutures.add(f);
}
});
LOG.warn("Waiting for " + forceCloseFutures.size() + " client channels to be closed.");
PromiseCombiner closePromisesCombiner = new PromiseCombiner(ImmediateEventExecutor.INSTANCE);
closePromisesCombiner.addAll(forceCloseFutures.toArray(new ChannelFuture[0]));
Promise<Void> combinedClosePromise = executor.newPromise();
closePromisesCombiner.finish(combinedClosePromise);
combinedClosePromise.await(5, TimeUnit.SECONDS);
LOG.warn(forceCloseFutures.size() + " client channels closed.");
} catch (InterruptedException ie) {
LOG.warn("Interrupted while shutting down client channels");
}
}
use of io.netty.util.concurrent.PromiseCombiner in project rest.li by linkedin.
the class Http2StreamCodec method write.
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (!(msg instanceof RequestWithCallback)) {
ctx.write(msg, promise);
return;
}
Request request = ((RequestWithCallback) msg).request();
Http2ConnectionEncoder encoder = encoder();
int streamId = connection().local().incrementAndGetNextStreamId();
if (request instanceof StreamRequest) {
LOG.debug("Writing StreamRequest...");
StreamRequest streamRequest = (StreamRequest) request;
Http2Headers http2Headers = NettyRequestAdapter.toHttp2Headers(streamRequest);
BufferedReader reader = new BufferedReader(ctx, encoder, streamId, ((RequestWithCallback) msg).handle());
streamRequest.getEntityStream().setReader(reader);
encoder.writeHeaders(ctx, streamId, http2Headers, NO_PADDING, NOT_END_STREAM, promise).addListener(future -> reader.request());
LOG.debug("Sent HTTP/2 HEADERS frame, stream={}, end={}, headers={}, padding={}bytes", new Object[] { streamId, NOT_END_STREAM, http2Headers.size(), NO_PADDING });
} else if (request instanceof RestRequest) {
LOG.debug("Writing RestRequest...");
PromiseCombiner promiseCombiner = new PromiseCombiner();
ChannelPromise headersPromise = ctx.channel().newPromise();
ChannelPromise dataPromise = ctx.channel().newPromise();
promiseCombiner.add(headersPromise);
promiseCombiner.add(dataPromise);
promiseCombiner.finish(promise);
RestRequest restRequest = (RestRequest) request;
Http2Headers headers = NettyRequestAdapter.toHttp2Headers(restRequest);
encoder.writeHeaders(ctx, streamId, headers, NO_PADDING, NOT_END_STREAM, headersPromise);
LOG.debug("Sent HTTP/2 HEADERS frame, stream={}, end={}, headers={}, padding={}bytes", new Object[] { streamId, NOT_END_STREAM, headers.size(), NO_PADDING });
ByteBuf data = Unpooled.wrappedBuffer(restRequest.getEntity().asByteBuffer());
encoder.writeData(ctx, streamId, data, NO_PADDING, END_STREAM, dataPromise);
LOG.debug("Sent HTTP/2 DATA frame, stream={}, end={}, data={}bytes, padding={}bytes", new Object[] { streamId, END_STREAM, data.readableBytes(), NO_PADDING });
} else {
// Request type is not supported. Returns channel back to the pool and throws exception.
ctx.fireChannelRead(((RequestWithCallback) msg).handle());
throw new IllegalArgumentException("Request is neither StreamRequest or RestRequest");
}
// Sets TransportCallback as a stream property to be retrieved later
TransportCallback<?> callback = ((RequestWithCallback) msg).callback();
Http2Connection.PropertyKey callbackKey = ctx.channel().attr(Http2ClientPipelineInitializer.CALLBACK_ATTR_KEY).get();
connection().stream(streamId).setProperty(callbackKey, callback);
// Sets AsyncPoolHandle as a stream property to be retrieved later
AsyncPoolHandle<?> handle = ((RequestWithCallback) msg).handle();
Http2Connection.PropertyKey handleKey = ctx.channel().attr(Http2ClientPipelineInitializer.CHANNEL_POOL_HANDLE_ATTR_KEY).get();
connection().stream(streamId).setProperty(handleKey, handle);
}
Aggregations