예제 #1
0
def submit_workflow(workflow_name: Text = None) -> WorkflowInfo:
    """
    Submits the user-defined workflow to the scheduler with the given name of workflow. Before the submission of
    workflow in Scheduler Service, the metadata of workflow will be registered in Metadata Service.

    The submission of workflow translates the current :class:`~ai_flow.ai_graph.ai_graph.AIGraph` , uploads the
    project package, registers the metadata of the specified workflow and submits the workflow by Scheduler Service
    which delegates the submission to the :class:`~ai_flow.plugin_interface.scheduler_interface.Scheduler`.

    :param workflow_name: The name of the workflow.
    :return: The :class:`~ai_flow.plugin_interface.scheduler_interface.WorkflowInfo` which contains the information
                 about the submitted workflow.
    """
    if current_graph().is_empty():
        raise EmptyGraphException("Cannot submit empty graph")
    entry_module_path = current_project_context().get_workflow_entry_module(workflow_name=workflow_name)
    namespace = current_project_config().get_project_name()
    translator = get_translator()
    workflow = translator.translate(graph=current_graph(), project_context=current_project_context())
    _apply_full_info_to_workflow(workflow, entry_module_path)
    current_graph().clear_graph()
    workflow_meta = get_ai_flow_client().get_workflow_by_name(project_name=current_project_config().get_project_name(),
                                                              workflow_name=workflow_name)
    if workflow_meta is None:
        get_ai_flow_client().register_workflow(name=workflow_name,
                                               project_id=int(current_project_config().get_project_uuid()))
    return proto_to_workflow(get_ai_flow_client()
                             .submit_workflow_to_scheduler(namespace=namespace,
                                                           workflow_json=json_utils.dumps(workflow),
                                                           workflow_name=workflow_name,
                                                           args={}))
    def test_two_rules_trigger_will_clear_all_event_life(self):
        condition = MeetAnyEventCondition() \
            .add_event(event_key="key_1", event_value="value_1", sender="1-job-name")
        rule1 = SchedulingRule(condition, action=JobAction.START)
        condition = MeetAllEventCondition() \
            .add_event(event_key="key_1", event_value="value_1", sender="1-job-name") \
            .add_event(event_key='key_2', event_value='value_2', sender="1-job-name")
        rule2 = SchedulingRule(condition, action=JobAction.STOP)

        configs = [rule1, rule2]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)
        event1: BaseEvent = BaseEvent(key='key_1',
                                      value='value_1',
                                      namespace='default',
                                      sender='1-job-name',
                                      create_time=round(time.time() * 1000))
        event2: BaseEvent = BaseEvent(key='key_2',
                                      value='value_2',
                                      namespace='default',
                                      sender='1-job-name',
                                      create_time=round(time.time() * 1000))
        action, ts = handler.handle_event(event2, None)
        self.assertEqual(SchedulingAction.NONE, action)
        action, ts = handler.handle_event(event1, ts)
        self.assertEqual(SchedulingAction.START, action)
        action, ts = handler.handle_event(event2, ts)
        self.assertEqual(SchedulingAction.NONE, action)
    def test_event_handler_schedule_time(self):
        condition = MeetAnyEventCondition() \
            .add_event(event_key="key_1", event_value="value_1", sender="1-job-name")
        rule1 = SchedulingRule(condition, action=JobAction.START)
        condition = MeetAllEventCondition() \
            .add_event(event_key="key_1", event_value="value_1", sender="1-job-name") \
            .add_event(event_key='key_2', event_value='value_2', sender="1-job-name")
        rule2 = SchedulingRule(condition, action=JobAction.STOP)

        configs = [rule1, rule2]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)

        event1_time = round(time.time() * 1000)
        event1: BaseEvent = BaseEvent(key='key_1',
                                      value='value_1',
                                      namespace='default',
                                      sender='1-job-name',
                                      create_time=event1_time)
        action, ts = handler.handle_event(event1, None)
        ts: AiFlowTs = ts
        self.assertEqual(event1_time, ts.rule_states[0].schedule_time)
        self.assertEqual(event1_time, ts.rule_states[0].latest_time)
        self.assertNotEqual(event1_time, ts.rule_states[1].schedule_time)
        self.assertEqual(event1_time, ts.rule_states[1].latest_time)
    def test_handle_task_status_change_event(self):
        from airflow.events.scheduler_events import TaskStateChangedEvent
        from airflow.utils.state import State

        rule1 = SchedulingRule(MeetAnyEventCondition().add_event(
            event_key="dag_1.task_1",
            event_value="RUNNING",
            event_type="TASK_STATUS_CHANGED",
            namespace="test",
            sender="task_1"), action=JobAction.START)
        rule2 = SchedulingRule(MeetAnyEventCondition().add_event(
            event_key="dag_1.task_1",
            event_value="FINISHED",
            event_type="TASK_STATUS_CHANGED",
            namespace="test",
            sender="task_1"), action=JobAction.STOP)
        configs = [rule1, rule2]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)

        event = TaskStateChangedEvent("task_1", "test.dag_1", datetime.utcnow(), State.RUNNING).to_event()
        action, ts = handler.handle_event(event, None)
        self.assertEqual(SchedulingAction.START, action)

        time.sleep(0.01)
        event = TaskStateChangedEvent("task_1", "test.dag_1", datetime.utcnow(), State.KILLING).to_event()
        action, ts = handler.handle_event(event, ts)
        self.assertEqual(SchedulingAction.NONE, action)

        time.sleep(0.01)
        event = TaskStateChangedEvent("task_1", "test.dag_1", datetime.utcnow(), State.SUCCESS).to_event()
        action, ts = handler.handle_event(event, ts)
        self.assertEqual(SchedulingAction.STOP, action)
    def test_multiple_any_config(self):
        rule = SchedulingRule(MeetAllEventCondition().add_event(
            event_key="key_1",
            event_value="value_1",
            event_type="*",
            namespace="*",
            sender="1-job-name"), action=JobAction.START)
        configs = [rule]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)
        event: BaseEvent = BaseEvent(key='key_1',
                                     value='value_1',
                                     namespace='default',
                                     sender='1-job-name',
                                     create_time=round(time.time() * 1000))
        action, ts = handler.handle_event(event, None)
        self.assertEqual(SchedulingAction.START, action)

        event: BaseEvent = BaseEvent(key='key_1',
                                     value='value_1',
                                     namespace='default',
                                     sender='aa',
                                     create_time=round(time.time() * 1000))
        action, ts = handler.handle_event(event, ts)
        self.assertEqual(SchedulingAction.NONE, action)

        event: BaseEvent = BaseEvent(key='key_1_1',
                                     value='value_1',
                                     namespace='default',
                                     sender='1-job-name',
                                     create_time=round(time.time() * 1000))
        action, ts = handler.handle_event(event, ts)
        self.assertEqual(SchedulingAction.NONE, action)
예제 #6
0
 def test_event_condition_serde(self):
     condition = EventCondition([], ConditionType.MEET_ANY)
     condition.add_event(event_key='k1', event_value='v1')
     condition.add_event(event_key='k2', event_value='v2')
     loaded_condition = json_utils.loads(json_utils.dumps(condition))
     self.assertEqual(condition, loaded_condition)
     loaded_condition.add_event(event_key='k1', event_value='v1')
     loaded_condition.add_event(event_key='k2', event_value='v2')
     self.assertEqual(condition, loaded_condition)
    def test_sender_any(self):
        rule = SchedulingRule(MeetAllEventCondition().add_event(
            event_key="key_1",
            event_value="value_1",
            namespace="aa",
            sender="*"), action=JobAction.START)
        configs = [rule]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)
        event: BaseEvent = BaseEvent(key='key_1',
                                     value='value_1',
                                     namespace='aa',
                                     sender='aa',
                                     create_time=int(time.time() * 1000))
        action, ts = handler.handle_event(event, None)
        self.assertEqual(SchedulingAction.START, action)

        event: BaseEvent = BaseEvent(key='key_1',
                                     value='value_1',
                                     namespace='aa',
                                     sender='bb',
                                     create_time=int(time.time() * 1000 + 1))
        action, ts = handler.handle_event(event, None)
        self.assertEqual(SchedulingAction.START, action)

        rule = SchedulingRule(MeetAllEventCondition().add_event(
            event_key="key_1",
            event_value="value_1",
            namespace="aa",
            sender="aa"), action=JobAction.START)
        configs = [rule]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)
        event: BaseEvent = BaseEvent(key='key_1',
                                     value='value_1',
                                     namespace='aa',
                                     sender='bb',
                                     create_time=int(time.time() * 1000))
        action, ts = handler.handle_event(event, None)
        self.assertEqual(SchedulingAction.NONE, action)
예제 #8
0
 def test_graph_serde(self):
     graph = Graph()
     nodes = []
     for i in range(3):
         node = Node(name=str(i))
         graph.add_node(node)
         nodes.append(node)
     edge = Edge(destination=nodes[0].node_id, source=nodes[1].node_id)
     graph.add_edge(nodes[0].node_id, edge)
     edge = Edge(destination=nodes[0].node_id, source=nodes[2].node_id)
     graph.add_edge(nodes[0].node_id, edge)
     json_text = json_utils.dumps(graph)
     g: Graph = json_utils.loads(json_text)
     self.assertEqual(3, len(g.nodes))
     self.assertEqual(2, len(graph.edges.get(nodes[0].node_id)))
예제 #9
0
 def test_workflow_serde(self):
     workflow_config_file = os.path.join(os.path.dirname(__file__), 'workflow_1.yaml')
     workflow_config = load_workflow_config(workflow_config_file)
     workflow = Workflow()
     workflow.workflow_config = workflow_config
     jobs = []
     for job_config in workflow_config.job_configs.values():
         job = Job(job_config=job_config)
         workflow.add_job(job)
         jobs.append(job)
     edge = ControlEdge(destination=jobs[0].job_name,
                        scheduling_rule=SchedulingRule(MeetAnyEventCondition().add_event('a', 'a'),
                                                       JobAction.START))
     workflow.add_edge(jobs[0].job_name, edge)
     edge = ControlEdge(destination=jobs[0].job_name,
                        scheduling_rule=SchedulingRule(MeetAnyEventCondition().add_event('b', 'b'),
                                                       JobAction.START))
     workflow.add_edge(jobs[0].job_name, edge)
     json_text = json_utils.dumps(workflow)
     w: Workflow = json_utils.loads(json_text)
     self.assertEqual(3, len(w.jobs))
     self.assertEqual(2, len(w.edges.get(jobs[0].job_name)))
    def test_unordered_event_life_repeated(self):
        condition = MeetAnyEventCondition() \
            .add_event(event_key="key_1", event_value="value_1", sender="1-job-name", life=EventLife.REPEATED)
        rule1 = SchedulingRule(condition, action=JobAction.START)

        configs = [rule1]
        config_str = json_utils.dumps(configs)
        handler = AIFlowHandler(config=config_str)
        event1: BaseEvent = BaseEvent(key='key_1',
                                      value='value_1',
                                      namespace='default',
                                      sender='1-job-name',
                                      create_time=round(time.time() * 1000))
        event1_in_past: BaseEvent = BaseEvent(key='key_1',
                                              value='value_1',
                                              namespace='default',
                                              sender='1-job-name',
                                              create_time=0)
        action, ts = handler.handle_event(event1, None)
        self.assertEqual(SchedulingAction.START, action)
        action, ts = handler.handle_event(event1_in_past, ts)
        self.assertEqual(SchedulingAction.START, action)
예제 #11
0
 def test_scheduling_rule_serde(self):
     condition = MeetAllEventCondition()
     action = JobAction.START
     rule = SchedulingRule(condition, action)
     loaded_rule = json_utils.loads(json_utils.dumps(rule))
     self.assertEqual(rule, loaded_rule)
 def __str__(self) -> str:
     return json_utils.dumps(self)
예제 #13
0
 def test_edge_serde(self):
     edge = Edge("a", 'b')
     json_text = json_utils.dumps(edge)
     c2: Edge = json_utils.loads(json_text)
     self.assertEqual(edge.source, c2.source)
예제 #14
0
 def test_node_serde(self):
     node = Node(name="a")
     json_text = json_utils.dumps(node)
     n2: Node = json_utils.loads(json_text)
     self.assertEqual(node.name, n2.name)