示例#1
0
    def _mark_agent_done(self, agent_info: AgentInfo) -> None:
        """
        Handle marking an agent as done, and telling the frontend agent
        that they have successfully completed their task.

        If the agent is in a final non-successful status, or already
        told of partner disconnect, skip
        """
        if agent_info.agent.db_status in AgentState.complete() + [
                AgentState.STATUS_PARTNER_DISCONNECT
        ]:
            return
        send_packet = Packet(
            packet_type=PACKET_TYPE_UPDATE_AGENT_STATUS,
            sender_id=SYSTEM_CHANNEL_ID,
            receiver_id=agent_info.agent.get_agent_id(),
            data={
                "status": "completed",
                "state": {
                    "done_text":
                    "You have completed this task. Please submit.",
                    "task_done": True,
                },
            },
        )
        channel_info = self.channels[agent_info.used_channel_id]
        channel_info.channel.send(send_packet)
示例#2
0
    def _handle_updated_agent_status(self, status_map: Dict[str, str]):
        """
        Handle updating the local statuses for agents based on
        the previously reported agent statuses.

        Takes as input a mapping from agent_id to server-side status
        """
        for agent_id, status in status_map.items():
            if status not in AgentState.valid():
                logger.warning(
                    f"Invalid status for agent {agent_id}: {status}")
                continue
            if agent_id not in self.agents:
                # no longer tracking agent
                continue
            agent = self.agents[agent_id].agent
            db_status = agent.get_status()
            if agent.has_updated_status.is_set():
                continue  # Incoming info may be stale if we have new info to send
            if status == AgentState.STATUS_NONE:
                # Stale or reconnect, send a status update
                self._send_status_update(self.agents[agent_id])
                continue
            if status != db_status:
                if db_status in AgentState.complete():
                    logger.info(
                        f"Got updated status {status} when already final: {agent.db_status}"
                    )
                    continue
                elif status == AgentState.STATUS_COMPLETED:
                    continue  # COMPLETED can only be marked locally
                agent.update_status(status)
        pass
示例#3
0
 def _launch_and_run_assignment(
     self,
     assignment: "Assignment",
     agent_infos: List["AgentInfo"],
     task_runner: "TaskRunner",
 ):
     """Launch a thread to supervise the completion of an assignment"""
     try:
         tracked_agents: List["Agent"] = []
         for a in agent_infos:
             assert isinstance(
                 a.agent, Agent
             ), f"Can launch assignments for Agents, not OnboardingAgents, got {a.agent}"
             tracked_agents.append(a.agent)
         task_runner.launch_assignment(assignment, tracked_agents)
         for agent_info in agent_infos:
             self._mark_agent_done(agent_info)
         # Wait for agents to be complete
         for agent_info in agent_infos:
             agent = agent_info.agent
             if agent.get_status() not in AgentState.complete():
                 if not agent.did_submit.is_set():
                     # Wait for a submit to occur
                     # TODO(#94) make submit timeout configurable
                     agent.has_action.wait(timeout=300)
                     agent.act()
                 agent.mark_done()
     except Exception as e:
         logger.exception(f"Cleaning up assignment: {e}", exc_info=True)
         task_runner.cleanup_assignment(assignment)
     finally:
         task_run = task_runner.task_run
         for unit in assignment.get_units():
             task_run.clear_reservation(unit)
示例#4
0
    def update_status(self, new_status: str) -> None:
        """Update the database status of this agent, and
        possibly send a message to the frontend agent informing
        them of this update"""
        if self.db_status == new_status:
            return  # Noop, this is already the case
        logger.debug(f"Updating {self} to {new_status}")
        if self.db_status in AgentState.complete():
            logger.info(f"Updating {self} from final status to {new_status}")

        old_status = self.db_status
        self.db.update_agent(self.db_id, status=new_status)
        self.db_status = new_status
        self.has_updated_status.set()
        if new_status in [
                AgentState.STATUS_RETURNED,
                AgentState.STATUS_DISCONNECT,
                AgentState.STATUS_TIMEOUT,
        ]:
            # Disconnect statuses should free any pending acts
            self.has_action.set()
            self.did_submit.set()
            if old_status == AgentState.STATUS_WAITING:
                # Waiting agents' unit can be reassigned, as no work
                # has been done yet.
                self.get_unit().clear_assigned_agent()
示例#5
0
 def mark_done(self) -> None:
     """
     Take any required step with the crowd_provider to ensure that
     the worker can submit their work and be marked as complete via
     a call to get_status
     """
     if self.get_status() not in AgentState.complete():
         self.db.update_agent(
             agent_id=self.db_id, status=AgentState.STATUS_COMPLETED
         )
示例#6
0
    def update_status(self, new_status: str) -> None:
        """Update the database status of this agent, and
        possibly send a message to the frontend agent informing
        them of this update"""
        if self.db_status == new_status:
            return  # Noop, this is already the case
        logger.debug(f"Updating {self} to {new_status}")
        if self.db_status in AgentState.complete():
            logger.info(f"Updating {self} from final status to {new_status}")

        old_status = self.db_status
        self.db.update_agent(self.db_id, status=new_status)
        self.db_status = new_status
        if self._associated_live_run is not None:
            live_run = self.get_live_run()
            live_run.loop_wrap.execute_coro(
                live_run.worker_pool.push_status_update(self))
        if new_status in [
                AgentState.STATUS_RETURNED,
                AgentState.STATUS_DISCONNECT,
                AgentState.STATUS_TIMEOUT,
        ]:
            # Disconnect statuses should free any pending acts
            self.has_live_update.set()
            self.did_submit.set()
            if old_status == AgentState.STATUS_WAITING:
                # Waiting agents' unit can be reassigned, as no work
                # has been done yet.
                unit = self.get_unit()
                logger.debug(
                    f"Clearing {self} from {unit} for update to {new_status}")
                unit.clear_assigned_agent()

        # Metrics changes
        ACTIVE_AGENT_STATUSES.labels(status=old_status,
                                     agent_type="main").dec()
        ACTIVE_AGENT_STATUSES.labels(status=new_status,
                                     agent_type="main").inc()
        if (old_status not in AgentState.complete()
                and new_status in AgentState.complete()):
            ACTIVE_WORKERS.labels(worker_id=self.worker_id,
                                  agent_type="main").dec()
示例#7
0
    def update_status(self, new_status: str) -> None:
        """Update the database status of this agent, and
        possibly send a message to the frontend agent informing
        them of this update"""
        if self.db_status == new_status:
            return  # Noop, this is already the case

        logger.debug(f"Updating {self} to {new_status}")
        if self.db_status in AgentState.complete():
            logger.info(f"Updating {self} from final status to {new_status}")

        old_status = self.db_status
        self.db.update_onboarding_agent(self.db_id, status=new_status)
        self.db_status = new_status
        if self._associated_live_run is not None:
            if new_status not in [
                    AgentState.STATUS_APPROVED,
                    AgentState.STATUS_REJECTED,
            ]:
                live_run = self.get_live_run()
                live_run.loop_wrap.execute_coro(
                    live_run.worker_pool.push_status_update(self))
        if new_status in [
                AgentState.STATUS_RETURNED, AgentState.STATUS_DISCONNECT
        ]:
            # Disconnect statuses should free any pending acts
            self.has_live_update.set()
            self.did_submit.set()

        # Metrics changes
        ACTIVE_AGENT_STATUSES.labels(status=old_status,
                                     agent_type="onboarding").dec()
        ACTIVE_AGENT_STATUSES.labels(status=new_status,
                                     agent_type="onboarding").inc()
        if (old_status not in AgentState.complete()
                and new_status in AgentState.complete()):
            ACTIVE_WORKERS.labels(worker_id=self.worker_id,
                                  agent_type="onboarding").dec()
示例#8
0
 def get_status(self) -> str:
     """Get the status of this agent in their work on their unit"""
     if self.db_status not in AgentState.complete():
         row = self.db.get_onboarding_agent(self.db_id)
         if row["status"] != self.db_status:
             if row["status"] in [
                     AgentState.STATUS_RETURNED,
                     AgentState.STATUS_DISCONNECT,
             ]:
                 # Disconnect statuses should free any pending acts
                 self.has_action.set()
             self.has_updated_status.set()
         self.db_status = row["status"]
     return self.db_status
示例#9
0
 def get_status(self) -> str:
     """Get the status of this agent in their work on their unit"""
     if self.db_status not in AgentState.complete():
         row = self.db.get_agent(self.db_id)
         if row["status"] != self.db_status:
             if row["status"] in [
                     AgentState.STATUS_RETURNED,
                     AgentState.STATUS_DISCONNECT,
             ]:
                 # Disconnect statuses should free any pending acts
                 self.has_live_update.set()
             if self._associated_live_run is not None:
                 live_run = self.get_live_run()
                 live_run.loop_wrap.execute_coro(
                     live_run.worker_pool.push_status_update(self))
         self.db_status = row["status"]
     return self.db_status
示例#10
0
 def update_status(self, new_status: str) -> None:
     """Update the database status of this agent, and
     possibly send a message to the frontend agent informing
     them of this update"""
     if self.db_status == new_status:
         return  # Noop, this is already the case
     if self.db_status in AgentState.complete():
         print(f"Updating a final status, was {self.db_status} "
               f"and want to set to {new_status}")
     self.db.update_onboarding_agent(self.db_id, status=new_status)
     self.db_status = new_status
     self.has_updated_status.set()
     if new_status in [
             AgentState.STATUS_RETURNED, AgentState.STATUS_DISCONNECT
     ]:
         # Disconnect statuses should free any pending acts
         self.has_action.set()
         self.did_submit.set()
示例#11
0
 def _launch_and_run_unit(self, unit: "Unit", agent_info: "AgentInfo",
                          task_runner: "TaskRunner"):
     """Launch a thread to supervise the completion of an assignment"""
     try:
         agent = agent_info.agent
         assert isinstance(
             agent, Agent
         ), f"Can launch units for Agents, not OnboardingAgents, got {agent}"
         task_runner.launch_unit(unit, agent)
         if agent.get_status() not in AgentState.complete():
             self._mark_agent_done(agent_info)
             if not agent.did_submit.is_set():
                 # Wait for a submit to occur
                 # TODO(#94) make submit timeout configurable
                 agent.has_action.wait(timeout=300)
                 agent.act()
             agent.mark_done()
     except Exception as e:
         logger.exception(f"Cleaning up unit: {e}", exc_info=True)
         task_runner.cleanup_unit(unit)
     finally:
         task_runner.task_run.clear_reservation(unit)