public class FlowControlHandler extends ChannelDuplexHandler
FlowControlHandler
ensures that only one message per read()
is sent downstream.
Classes such as ByteToMessageDecoder
or MessageToByteEncoder
are free to emit as
many events as they like for any given input. A channel's auto reading configuration doesn't usually
apply in these scenarios. This is causing problems in downstream ChannelHandler
s that would
like to hold subsequent events while they're processing one event. It's a common problem with the
HttpObjectDecoder
that will very often fire a HttpRequest
that is immediately followed
by a LastHttpContent
event.
{@code ChannelPipeline pipeline = ...; pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new FlowControlHandler()); pipeline.addLast(new MyExampleHandler()); class MyExampleHandler extends ChannelInboundHandlerAdapter {
ChannelConfig.setAutoRead(boolean)
Modifier and Type | Class and Description |
---|---|
private static class |
FlowControlHandler.RecyclableArrayDeque
A recyclable
ArrayDeque . |
ChannelHandler.Sharable
Modifier and Type | Field and Description |
---|---|
private ChannelConfig |
config |
private static InternalLogger |
logger |
private FlowControlHandler.RecyclableArrayDeque |
queue |
private boolean |
releaseMessages |
private boolean |
shouldConsume |
Constructor and Description |
---|
FlowControlHandler() |
FlowControlHandler(boolean releaseMessages) |
Modifier and Type | Method and Description |
---|---|
void |
channelInactive(ChannelHandlerContext ctx)
Calls
ChannelHandlerContext.fireChannelInactive() to forward
to the next ChannelInboundHandler in the ChannelPipeline . |
void |
channelRead(ChannelHandlerContext ctx,
java.lang.Object msg)
Calls
ChannelHandlerContext.fireChannelRead(Object) to forward
to the next ChannelInboundHandler in the ChannelPipeline . |
void |
channelReadComplete(ChannelHandlerContext ctx)
Calls
ChannelHandlerContext.fireChannelReadComplete() to forward
to the next ChannelInboundHandler in the ChannelPipeline . |
private int |
dequeue(ChannelHandlerContext ctx,
int minConsume)
Dequeues one or many (or none) messages depending on the channel's auto
reading state and returns the number of messages that were consumed from
the internal queue.
|
private void |
destroy()
Releases all messages and destroys the
Queue . |
void |
handlerAdded(ChannelHandlerContext ctx)
Do nothing by default, sub-classes may override this method.
|
(package private) boolean |
isQueueEmpty()
Determine if the underlying
Queue is empty. |
void |
read(ChannelHandlerContext ctx)
Calls
ChannelHandlerContext.read() to forward
to the next ChannelOutboundHandler in the ChannelPipeline . |
bind, close, connect, deregister, disconnect, flush, write
channelActive, channelRegistered, channelUnregistered, channelWritabilityChanged, exceptionCaught, userEventTriggered
ensureNotSharable, handlerRemoved, isSharable
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
exceptionCaught, handlerRemoved
private static final InternalLogger logger
private final boolean releaseMessages
private FlowControlHandler.RecyclableArrayDeque queue
private ChannelConfig config
private boolean shouldConsume
public FlowControlHandler()
public FlowControlHandler(boolean releaseMessages)
boolean isQueueEmpty()
Queue
is empty. This method exists for
testing, debugging and inspection purposes and it is not Thread safe!private void destroy()
Queue
.public void handlerAdded(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelHandlerAdapter
handlerAdded
in interface ChannelHandler
handlerAdded
in class ChannelHandlerAdapter
java.lang.Exception
public void channelInactive(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelInboundHandlerAdapter
ChannelHandlerContext.fireChannelInactive()
to forward
to the next ChannelInboundHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.channelInactive
in interface ChannelInboundHandler
channelInactive
in class ChannelInboundHandlerAdapter
java.lang.Exception
public void read(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelDuplexHandler
ChannelHandlerContext.read()
to forward
to the next ChannelOutboundHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.read
in interface ChannelOutboundHandler
read
in class ChannelDuplexHandler
java.lang.Exception
public void channelRead(ChannelHandlerContext ctx, java.lang.Object msg) throws java.lang.Exception
ChannelInboundHandlerAdapter
ChannelHandlerContext.fireChannelRead(Object)
to forward
to the next ChannelInboundHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.channelRead
in interface ChannelInboundHandler
channelRead
in class ChannelInboundHandlerAdapter
java.lang.Exception
public void channelReadComplete(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelInboundHandlerAdapter
ChannelHandlerContext.fireChannelReadComplete()
to forward
to the next ChannelInboundHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.channelReadComplete
in interface ChannelInboundHandler
channelReadComplete
in class ChannelInboundHandlerAdapter
java.lang.Exception
private int dequeue(ChannelHandlerContext ctx, int minConsume)
minConsume
argument is used to force dequeue()
into
consuming that number of messages regardless of the channel's auto
reading configuration.