docs: def handle_request(self, connection, msg):
          """Dispatch a request message to the appropriate method.
  
          Parameters
          ----------
          connection : ClientConnection object
              The client connection the message was from.
          msg : Message object
              The request message to process.
  
          Returns
          -------
          done_future : Future or None
              Returns Future for async request handlers that will resolve when
              done, or None for sync request handlers once they have completed.
  
          """
          send_reply = True
          # TODO Should check presence of Message-ids against protocol flags and
          # raise an error as needed.
          if msg.name in self._request_handlers:
              req_conn = ClientRequestConnection(connection, msg)
              handler = self._request_handlers[msg.name]
              try:
                  reply = handler(self, req_conn, msg)
                  # If we get a future, assume this is an async message handler
                  # that will resolve the future with the reply message when it
                  # is complete. Attach a message-sending callback to the future,
                  # and return the future.
                  if gen.is_future(reply):
                      concurrent = getattr(handler, '_concurrent_reply', False)
                      concurrent_str = ' CONCURRENT' if concurrent else ''
  
                      done_future = Future()
                      def async_reply(f):
                          try:
                              connection.reply(f.result(), msg)
                              self._logger.debug("%s FUTURE%s replied",
                                                 msg.name, concurrent_str)
                          except FailReply, e:
                              reason = str(e)
                              self._logger.error("Request %s FUTURE%s FAIL: %s",
                                                 msg.name, concurrent_str, reason)
                              reply = Message.reply(msg.name, "fail", reason)
                              connection.reply(reply, msg)
                          except AsyncReply:
                              self._logger.debug("%s FUTURE ASYNC OK"
                                                 % (msg.name,))
                          except Exception:
                              error_reply = self.create_exception_reply_and_log(
                                  msg, sys.exc_info())
                              connection.reply(error_reply, msg)
                          finally:
                              done_future.set_result(None)
  
                      # TODO When using the return_reply() decorator the future
                      # returned is not currently threadsafe, must either deal
                      # with it here, or in kattypes.py. Would be nice if we don't
                      # have to always fall back to adding a callback, or wrapping
                      # a thread-safe future. Supporting sync-with-thread and
                      # async futures is turning out to be a pain in the ass ;)
                      self.ioloop.add_callback(reply.add_done_callback, async_reply)
                      # reply.add_done_callback(async_reply)
  
                      if concurrent:
                          # Return immediately if this is a concurrent handler
                          self._logger.debug("%s FUTURE CONCURRENT OK", msg.name)
                          return
                      else:
                          self._logger.debug("%s FUTURE OK", msg.name)
                          return done_future
                  else:
                      assert (reply.mtype == Message.REPLY)
                      assert (reply.name == msg.name)
                      self._logger.debug("%s OK" % (msg.name,))
              except AsyncReply, e:
                  self._logger.debug("%s ASYNC OK" % (msg.name,))
                  send_reply = False
              except FailReply, e:
                  reason = str(e)
                  self._logger.error("Request %s FAIL: %s" % (msg.name, reason))
                  reply = Message.reply(msg.name, "fail", reason)
              except Exception:
                  reply = self.create_exception_reply_and_log(msg, sys.exc_info())
          else:
              self._logger.error("%s INVALID: Unknown request." % (msg.name,))
              reply = Message.reply(msg.name, "invalid", "Unknown request.")
  
          if send_reply:
              connection.reply(reply, msg)