docs: def _Process(self, request, responses, thread_pool=None, events=None):
      """Hunts process all responses concurrently in a threadpool."""
      # This function is called and runs within the main processing thread. We do
      # not need to lock the hunt object while running in this method.
      if request.next_state == "AddClient":
        if not self.IsHuntStarted():
          logging.debug(
              "Unable to start client %s on hunt %s which is in state %s",
              request.client_id, self.session_id,
              self.hunt_obj.Get(self.hunt_obj.Schema.STATE))
          return
  
        # Get the client count.
        client_count = int(
            self.hunt_obj.Get(self.hunt_obj.Schema.CLIENT_COUNT, 0))
  
        # Pause the hunt if we exceed the client limit.
        if 0 < self.runner_args.client_limit <= client_count:
          # Remove our rules from the foreman so we dont get more clients sent to
          # this hunt. Hunt will be paused.
          self.Pause()
  
          # Ignore this client since it had gone over the limit.
          return
  
        # Update the client count.
        self.hunt_obj.Set(self.hunt_obj.Schema.CLIENT_COUNT(client_count + 1))
  
        # Add client to list of clients and optionally run it
        # (if client_rate == 0).
  
        self._AddClient(request.client_id)
        return
  
      if request.next_state == "RegisterClient":
        state = self.hunt_obj.Get(self.hunt_obj.Schema.STATE)
        # This allows the client limit to operate with a client rate. We still
        # want clients to get registered for the hunt at times in the future.
        # After they have been run, hunts only ever go into the paused state by
        # hitting the client limit. If a user stops a hunt, it will go into the
        # "STOPPED" state.
        if state in ["STARTED", "PAUSED"]:
          self._RegisterAndRunClient(request.client_id)
        else:
          logging.debug(
              "Not starting client %s on hunt %s which is not running: %s",
              request.client_id, self.session_id,
              self.hunt_obj.Get(self.hunt_obj.Schema.STATE))
        return
  
      event = threading.Event()
      events.append(event)
      # In a hunt, all requests are independent and can be processed
      # in separate threads.
      thread_pool.AddTask(
          target=self.RunStateMethod,
          args=(request.next_state, request, responses, event),
          name="Hunt processing")