code: def process_message(self, message):
          
          try:
              self.logger.debug("Received message %s with id %r.", message, message.message_id)
              self.broker.emit_before("process_message", message)
  
              res = None
              if not message.failed:
                  actor = self.broker.get_actor(message.actor_name)
                  res = actor(*message.args, **message.kwargs)
  
              self.broker.emit_after("process_message", message, result=res)
  
          except SkipMessage:
              self.logger.warning("Message %s was skipped.", message)
              self.broker.emit_after("skip_message", message)
  
          except BaseException as e:
              # Stuff the exception into the message [proxy] so that it
              # may be used by the stub broker to provide a nicer
              # testing experience.
              message.stuff_exception(e)
  
              if isinstance(e, RateLimitExceeded):
                  self.logger.warning("Rate limit exceeded in message %s: %s.", message, e)
              else:
                  self.logger.warning("Failed to process message %s with unhandled exception.", message, exc_info=True)
  
              self.broker.emit_after("process_message", message, exception=e)
  
          finally:
              # NOTE: There is no race here as any message that was
              # processed must have come off of a consumer.  Therefore,
              # there has to be a consumer for that message's queue so
              # this is safe.  Probably.
              self.consumers[message.queue_name].post_process_message(message)
              self.work_queue.task_done()
docs: Process a message pulled off of the work queue then push it
          back to its associated consumer for post processing.
  
          Parameters:
            message(MessageProxy)