@Override
  public synchronized void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
      throws Exception {
    channel = ctx.getChannel();

    List<Command<K, V, ?>> tmp = new ArrayList<Command<K, V, ?>>(queue.size() + 2);

    if (password != null) {
      CommandArgs<K, V> args = new CommandArgs<K, V>(codec).add(password);
      tmp.add(new Command<K, V, String>(AUTH, new StatusOutput<K, V>(codec), args, false));
    }

    if (db != 0) {
      CommandArgs<K, V> args = new CommandArgs<K, V>(codec).add(db);
      tmp.add(new Command<K, V, String>(SELECT, new StatusOutput<K, V>(codec), args, false));
    }

    tmp.addAll(queue);
    queue.clear();

    for (Command<K, V, ?> cmd : tmp) {
      if (!cmd.isCancelled()) {
        queue.add(cmd);
        channel.write(cmd);
      }
    }

    tmp.clear();
  }
 public <T> T await(Command<K, V, T> cmd, long timeout, TimeUnit unit) {
   if (!cmd.await(timeout, unit)) {
     cmd.cancel(true);
     throw new RedisException("Command timed out");
   }
   CommandOutput<K, V, T> output = cmd.getOutput();
   if (output.hasError()) throw new RedisException(output.getError());
   return output.get();
 }
 @Override
 public synchronized void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
     throws Exception {
   if (closed) {
     for (Command<K, V, ?> cmd : queue) {
       cmd.getOutput().setError("Connection closed");
       cmd.complete();
     }
     queue.clear();
     queue = null;
     channel = null;
   }
 }
  @Test
  public void testExceptionWithQueue() throws Exception {
    sut.setState(CommandHandler.LifecycleState.ACTIVE);
    q.clear();

    sut.channelActive(context);
    when(channel.isActive()).thenReturn(true);

    q.add(command);
    sut.exceptionCaught(context, new Exception());

    assertThat(q).isEmpty();
    assertThat(command.getException()).isNotNull();

    verify(context).fireExceptionCaught(any(Exception.class));
  }