Example #1
0
    def test_key_mapping_decision(self):
        """

        :return:
        """
        dec = decision.KeyMappingDecisionMaker({"key": "value"}, "strategy")
        message1 = framework.OperationMessage("SENSED_MESSAGE", "id1",
                                              {"strategy": "key"})
        message2 = framework.OperationMessage("SENSED_MESSAGE", "id1", {})
        self.assertIsInstance(dec.decision_logic(message1),
                              framework.OperationMessage)
        self.assertRaises(exception.ETypeMismatch, dec.decision_logic,
                          message2)
Example #2
0
    def decision_logic(self, message):
        """

        :param message:
        :return:
        """
        decided_message = framework.OperationMessage("DECIDED_MESSAGE",
                                                     message.operation_id,
                                                     message.params)
        return decided_message
Example #3
0
    def test_callback_executor(self, mock_send):
        """

        :return:
        """
        mock_send.return_value = None
        exe = executor.CallbackExecutor(DemoExecFuncSet())
        message = framework.OperationMessage("DECIDED_MESSAGE", "id1",
                                             {".inner_executor_key": "demo"})
        ret = exe.execute_message(message)
        self.assertDictEqual(ret, {"code": 0})
Example #4
0
    def decision_logic(self, message):
        """
        状态机决策逻辑,该函数直接根据Message生成决策完成的消息对象

        :param Message message: 感知完成的消息对象
        :return: 决策完成的消息对象
        :rtype: Message
        """
        decided_message = framework.OperationMessage(
            "DECIDED_MESSAGE", message.operation_id, message.params)
        return decided_message
Example #5
0
    def test_multi_process_executor(self, mock_send):
        """

        :return:
        """
        mock_send.return_value = None
        exe = executor.MultiProcessExecutor()
        mes1 = framework.IDLEMessage()
        mes2 = framework.OperationMessage("DECIDED_MESSAGE", "id1", {})
        exe.on_execute_message(mes1)
        exe.on_execute_message(mes2)
        exe.on_execute_message(mes1)
        mes3 = framework.OperationMessage("SENSED_MESSAGE", "id1", {})
        self.assertRaises(exception.EUnknownEvent, exe.on_execute_message,
                          mes3)
        exe._concerned_message_list = [
            "IDLE_MESSAGE", "DECIDED_MESSAGE", "SENSED_MESSAGE"
        ]
        exe.on_execute_message(mes3)

        self.assertRaises(exception.ENotImplement, exe.execute_message, mes3)
Example #6
0
    def test_messagepumb(self):
        """

        :return:
        """
        listener1 = framework.Listener()
        listener1.register(["IDLE_MESSAGE", "SENSED_MESSAGE"])
        listener2 = framework.Listener()
        pumb = framework.MessagePump()
        pumb.add_listener(listener1)
        self.assertRaises(ValueError, pumb.del_listener, listener2)
        concern = pumb.list_listener_concern(listener1)
        self.assertItemsEqual(["IDLE_MESSAGE", "SENSED_MESSAGE"], concern)

        message_operation = framework.OperationMessage(
            "SENSED_MESSAGE", "id2", {})
        message_operation2 = framework.OperationMessage(
            "DECIDED_MESSAGE", "id3", {})
        thread = threading.Thread(
            target=self.__run_thread_assistant, args=(pumb, ))
        thread.daemon = True
        thread.start()

        time.sleep(1)
        pumb.send(message_operation)
        pumb.send(message_operation2)
        time.sleep(3)
        pumb._stop_tag = True
        time.sleep(2)

        sen = framework.BaseSensor()
        dec = framework.BaseDecisionMaker()
        exe = framework.BaseExecutor()
        assistant_sensor = "demo"
        pumb._listener_list = [sen, dec, exe]
        pumb.validate_listeners()
        pumb.add_listener(dec)
        self.assertRaises(exception.ETypeMismatch, pumb.validate_listeners)
        pumb._listener_list = [sen,dec, exe, assistant_sensor]
        self.assertRaises(exception.ETypeMismatch, pumb.validate_listeners)
Example #7
0
    def test_decision_maker(self, mock_dec, mock_send):
        """

        :return:
        """
        mock_send.return_value = None
        mock_dec.return_value = framework.IDLEMessage()
        dec = decision.DecisionMaker()
        message = framework.IDLEMessage()
        mes_sen = framework.OperationMessage("SENSED_MESSAGE", "ID1", {})
        dec.on_decision_message(mes_sen)
        mes_complete = framework.OperationMessage("COMPLETE_MESSAGE", "ID1",
                                                  {})
        dec.on_decision_message(mes_complete)
        dec._concerned_message_list = [
            "SENSED_MESSAGE", "COMPLETE_MESSAGE", "IDLE_MESSAGE"
        ]
        dec.on_decision_message(message)
        mes_unconcerned = framework.OperationMessage("UNKNOWN_MESSAGE", "ID1",
                                                     {})
        self.assertRaises(exception.EUnknownEvent, dec.on_decision_message,
                          mes_unconcerned)
Example #8
0
    def test_message(self):
        """

        :return:
        """
        mes = framework.Message("IDLE_MESSAGE")
        self.assertEqual("IDLE_MESSAGE", mes.name)

        mes = framework.IDLEMessage()
        self.assertEqual("IDLE_MESSAGE", mes.name)

        mes = framework.OperationMessage("SENSED_MESSAGE", "id1", {})
        self.assertEqual("SENSED_MESSAGE", mes.name)
        self.assertEqual("id1", mes.operation_id)
        self.assertDictEqual({}, mes.params)
        mes.params = {"a":"b"}
        self.assertDictEqual({"a":"b"}, mes.params)
Example #9
0
    def message_handler(self, message):
        """
        消息处理逻辑,该函数调用具体的消息执行函数,并获取结果放入结果队列中

        .. Note:: 由于操作异步执行,因此各子进程执行结果统一放入多进程安全的结果队列,
                 由主进程统一进程结果的后续处理

        :param Message message: 消息对象
        :return: 无返回
        :rtype: None
        """
        try:
            ret = self.execute_message(message)
        except Exception as e:
            ret = "err:{}".format(e)

        message = framework.OperationMessage("COMPLETE_MESSAGE",
                                             message.operation_id, ret)
        self._result_queue.put(message)
        return
Example #10
0
    def decision_logic(self, message):
        """
        具体决策逻辑

        :param Message message: 消息对象
        :return: 决策完成的消息
        :rtype: Message
        :raises ETypeMismatch: 事件参数不匹配异常
        """
        log.info("begin decision logic, message:{}".format(message.name))
        operation_id = message.operation_id
        params = message.params
        if self._from_key in params \
                and params[self._from_key] in self._mapping:
            params_cp = copy.deepcopy(params)
            params_cp[self._to_key] = self._mapping[params_cp[self._from_key]]
            decided_message = framework.OperationMessage(
                "DECIDED_MESSAGE", operation_id, params_cp)
            return decided_message
        else:
            raise exception.ETypeMismatch(
                "{} not in params or params[{}] not in "
                "mapping".format(self._from_key, self._from_key))
Example #11
0
    def graph_start(self, state_machine):
        """
        状态机启动执行。状态机启动后,会根据每个节点执行的返回值,执行下一个节点,直到返回
        结束或执行异常。在每个节点执行完成后,会向结果队列中发送消息,由主进程进行处理

        :param StateMachine state_machine: 状态机实例
        :return: 无返回
        :rtype: None
        """
        session = state_machine.session
        while True:
            try:
                control = copy.deepcopy(self._control_message[session.id])
            except KeyError:
                control = None
            if control is not None:
                # 状态机第一次处理控制消息或控制消息为最新还没被处理
                if session.last_control_id is None \
                        or session.last_control_id != control['control_id']:
                    control_message = copy.deepcopy(control['message'])
                    session.last_control_id = control['control_id']
                else:
                    control_message = None
            else:
                control_message = None
            session.control_message = control_message

            #第一次运行的状态机,记录第一个节点信息
            if state_machine.status == state_machine.Status.INITED:
                todo_params = state_machine.dump()
                todo_node = todo_params["current_node"]
                todo_params = {
                    "session": session,
                    "finished_node": None,
                    "current_node": todo_node,
                    "timestamp": int(time.time())
                }
                todo_notice = framework.OperationMessage(
                    "STATE_COMPLETE_MESSAGE", str(session.id), todo_params)
                self._result_queue.put(todo_notice)
                state_machine.status = state_machine.Status.RUNNING

            if state_machine.status == state_machine.Status.RUNNING:
                try:
                    log.info("state machine run state:{}".format(session.id))
                    todo_params = state_machine.dump()
                    todo_node = todo_params["current_node"]

                    state_machine.run_next()
                    finished_params = state_machine.dump()
                    session.status = finished_params["status"]
                    #状态机Session的current_node为节点,而不再是节点的名称
                    session.current_node = state_machine.get_node(
                        finished_params["current_node"])
                    session.nodes_process = copy.copy(
                        finished_params["nodes_process"])
                    session.nodes_process[session.current_node] = True
                    current_node = session.current_node if \
                        session.current_node.name != "ARK_NODE_END" else None
                    params = {
                        "session": session,
                        "finished_node": todo_node,
                        "current_node": current_node,
                        "timestamp": int(time.time())
                    }
                    notice = framework.OperationMessage(
                        "STATE_COMPLETE_MESSAGE", str(session.id), params)
                    if todo_node != current_node or session.reset_flush(
                    ):  #节点变更或业务方指定持久化Session
                        self._result_queue.put(notice)

                except Exception as e:
                    log.warning("graph run exception:{}".format(e))
                    log.warning("err:{}".format(traceback.format_exc()))
                    state_machine.status = state_machine.Status.FAILED
                    break
            else:
                break
        del self._control_message[session.id]
        log.info("state machine run finished, operationId:{}".format(
            session.id))
Example #12
0
    def graph_start(self, state_machine):
        """
        状态机启动执行。状态机启动后,会根据每个节点执行的返回值,执行下一个节点,直到返回
        结束或执行异常。在每个节点执行完成后,会向结果队列中发送消息,由主进程进行处理

        :param StateMachine state_machine: 状态机实例
        :return: 无返回
        :rtype: None
        """
        session = state_machine.session
        while True:
            try:
                control_message = copy.deepcopy(
                    self._control_message[session.id])
            except KeyError:
                control_message = None
            session.control_message = control_message
            self._control_message[session.id] = None

            #第一次运行的状态机,记录第一个节点信息
            if state_machine.status == state_machine.Status.INITED:
                todo_params = state_machine.dump()
                todo_node = todo_params["current_node"]
                todo_params = {
                    "session": session,
                    "finished_node": None,
                    "current_node": todo_node,
                    "timestamp": int(time.time())
                }
                todo_notice = framework.OperationMessage(
                    "STATE_COMPLETE_MESSAGE", str(session.id), todo_params)
                self._result_queue.put(todo_notice)
                state_machine.status = state_machine.Status.RUNNING

            if state_machine.status == state_machine.Status.RUNNING:
                try:
                    log.info("state machine run state:{}".format(session.id))
                    todo_params = state_machine.dump()
                    todo_node = todo_params["current_node"]
                    state_machine.run_next()
                    finished_params = state_machine.dump()
                    session.status = finished_params["status"]
                    session.current_node = finished_params["current_node"]
                    session.nodes_process = copy.copy(
                        finished_params["nodes_process"])
                    session.nodes_process[session.current_node] = True
                    current_node = session.current_node if \
                        session.current_node != "ARK_NODE_END" else None
                    params = {
                        "session": session,
                        "finished_node": todo_node,
                        "current_node": current_node,
                        "timestamp": int(time.time())
                    }
                    notice = framework.OperationMessage(
                        "STATE_COMPLETE_MESSAGE", str(session.id), params)
                    self._result_queue.put(notice)
                except Exception as e:
                    log.warning("graph run exception:{}".format(e))
                    log.warning("err:{}".format(traceback.format_exc()))
                    state_machine.status = state_machine.Status.FAILED
                    break
            else:
                break
        del self._control_message[session.id]
        log.info("state machine run finished, operationId:{}".format(
            session.id))
        message = framework.OperationMessage("COMPLETE_MESSAGE",
                                             str(session.id), session.__dict__)
        self._result_queue.put(message)