@Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
    Throwable cause = e.getCause();

    if (!(cause instanceof ConnectException)) {
      stats.accumulateOutcomeWithDelta(Outcome.UNHANDLED_FAILURE, 0);
    }
    scheduleReconnect();
  }
  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {

    ResultCode success;
    ChannelBuffer buf = (ChannelBuffer) e.getMessage();
    TMemoryInputTransport trans = new TMemoryInputTransport(buf.array());
    TBinaryProtocol proto = new TBinaryProtocol(trans);
    TMessage msg = proto.readMessageBegin();
    if (msg.type == TMessageType.EXCEPTION) {
      proto.readMessageEnd();
    }
    TField field;
    proto.readStructBegin();
    while (true) {
      field = proto.readFieldBegin();
      if (field.type == TType.STOP) {
        break;
      }
      switch (field.id) {
        case 0: // SUCCESS
          if (field.type == TType.I32) {
            success = ResultCode.findByValue(proto.readI32());
            stats.accumulateOutcomeWithDelta(
                success.getValue() == 0 ? Outcome.SUCCESS : Outcome.GRACEFUL_FAILURE, 0);
          } else {
            TProtocolUtil.skip(proto, field.type);
          }
          break;
        default:
          TProtocolUtil.skip(proto, field.type);
      }
      proto.readFieldEnd();
    }
    proto.readStructEnd();
    proto.readMessageEnd();
  }