@Override
  public void disconnect(String scaleDownNodeID, final boolean criticalError) {
    Channel channel0 = getChannel(ChannelImpl.CHANNEL_ID.PING.id, -1);

    // And we remove all channels from the connection, this ensures no more packets will be
    // processed after this
    // method is
    // complete

    Set<Channel> allChannels = new HashSet<>(channels.values());

    if (!criticalError) {
      removeAllChannels();
    } else {
      // We can't hold a lock if a critical error is happening...
      // as other threads will be holding the lock while hanging on IO
      channels.clear();
    }

    // Now we are 100% sure that no more packets will be processed we can flush then send the
    // disconnect

    if (!criticalError) {
      for (Channel channel : allChannels) {
        channel.flushConfirmations();
      }
    }
    Packet disconnect;

    if (channel0.supports(PacketImpl.DISCONNECT_V2)) {
      disconnect = new DisconnectMessage_V2(nodeID, scaleDownNodeID);
    } else {
      disconnect = new DisconnectMessage(nodeID);
    }
    channel0.sendAndFlush(disconnect);
  }