package org.robotninjas.riemann.client; import com.aphyr.riemann.Proto; import org.jboss.netty.channel.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import static org.jboss.netty.channel.Channels.write; class ReturnableHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler { private final BlockingQueue<ReturnableMessage> returnables; private final Executor executor = Executors.newSingleThreadExecutor(); public ReturnableHandler(BlockingQueue<ReturnableMessage> returnables) { this.returnables = returnables; } @Override public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception { if (e instanceof MessageEvent) { final MessageEvent msgEvent = (MessageEvent) e; if (((MessageEvent) e).getMessage() instanceof ReturnableMessage<?>) { final ReturnableMessage returnable = (ReturnableMessage<?>) msgEvent.getMessage(); // strip the returnable and send the protobuf downstream write(ctx, e.getFuture(), returnable.getMsg(), ((MessageEvent) e).getRemoteAddress()); returnables.put(returnable); return; } else { ctx.sendDownstream(e); } } else if (e instanceof ChannelStateEvent) { final ChannelStateEvent stateEvent = (ChannelStateEvent) e; if (stateEvent.getState() == ChannelState.OPEN && (Boolean) stateEvent.getValue() == false) { // channel was closed for (ReturnableMessage returnable : returnables) { returnable.cancel(true); } returnables.clear(); } } ctx.sendDownstream(e); } @Override public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception { if (e instanceof MessageEvent) { final MessageEvent msgEvent = (MessageEvent) e; final ReturnableMessage returnable = returnables.poll(); final Proto.Msg msg = (Proto.Msg) msgEvent.getMessage(); returnable.handleResult(msg); } ctx.sendUpstream(e); } }