diff --git a/serverlessworkflow/sdk/state_machine_generator.py b/serverlessworkflow/sdk/state_machine_generator.py index a1e118b..f2ce36b 100644 --- a/serverlessworkflow/sdk/state_machine_generator.py +++ b/serverlessworkflow/sdk/state_machine_generator.py @@ -23,7 +23,6 @@ from serverlessworkflow.sdk.transition_data_condition import TransitionDataCondition from serverlessworkflow.sdk.end_data_condition import EndDataCondition -from transitions.extensions import HierarchicalMachine, GraphMachine from transitions.extensions.nesting import NestedState import warnings @@ -260,7 +259,67 @@ def sleep_state_details(self): def event_state_details(self): if isinstance(self.current_state, EventState): - self.state_to_machine_state(["event_state", "state"]) + state = self.state_to_machine_state(["event_state", "state"]) + if self.get_actions: + if on_events := self.current_state.onEvents: + state.initial = [] if len(on_events) > 1 else on_events[0] + for i, oe in enumerate(on_events): + state.add_substate( + oe_state := self.state_machine.state_cls( + oe_name := f"onEvent {i}" + ) + ) + + # define initial state + if i == 0 and len(on_events) > 1: + state.initial = [oe_state.name] + elif i == 0 and len(on_events) == 1: + state.initial = oe_state.name + else: + state.initial.append(oe_state.name) + + event_names = [] + for ie, event in enumerate(oe.eventRefs): + oe_state.add_substate( + ns := self.state_machine.state_cls(event) + ) + ns.tags = ["event"] + self.get_action_event(state=ns, e_name=event) + event_names.append(event) + + # define initial state + if ie == 0 and len(oe.eventRefs) > 1: + oe_state.initial = [event] + elif ie == 0 and len(oe.eventRefs) == 1: + oe_state.initial = event + else: + oe_state.initial.append(event) + + if self.current_state.exclusive: + oe_state.add_substate( + ns := self.state_machine.state_cls( + action_name := f"action {ie}" + ) + ) + self.state_machine.add_transition( + trigger="", + source=f"{self.current_state.name}.{oe_name}.{event}", + dest=f"{self.current_state.name}.{oe_name}.{action_name}", + ) + self.generate_actions_info( + machine_state=ns, + state_name=f"{self.current_state.name}.{oe_name}.{action_name}", + actions=oe.actions, + action_mode=oe.actionMode, + ) + if not self.current_state.exclusive and oe.actions: + self.generate_actions_info( + machine_state=oe_state, + state_name=f"{self.current_state.name}.{oe_name}", + actions=oe.actions, + action_mode=oe.actionMode, + initial_states=event_names, + ) def foreach_state_details(self): if isinstance(self.current_state, ForEachState): @@ -353,6 +412,7 @@ def generate_actions_info( state_name: str, actions: List[Dict[str, Action]], action_mode: str = "sequential", + initial_states: List[str] = [], ): if self.get_actions: parallel_states = [] @@ -387,7 +447,11 @@ def generate_actions_info( ns := self.state_machine.state_cls(name) ) ns.tags = ["event"] - self.get_action_event(state=ns, e_name=name) + self.get_action_event( + state=ns, + e_name=action.eventRef.triggerEventRef, + er_name=action.eventRef.resultEventRef, + ) if name: if action_mode == "sequential": if i < len(actions) - 1: @@ -439,19 +503,36 @@ def generate_actions_info( ) ns.tags = ["event"] self.get_action_event( - state=ns, e_name=next_name + state=ns, + e_name=action.eventRef.triggerEventRef, + er_name=action.eventRef.resultEventRef, ) self.state_machine.add_transition( trigger="", source=f"{state_name}.{name}", dest=f"{state_name}.{next_name}", ) - if i == 0: + if i == 0 and not initial_states: machine_state.initial = name + elif i == 0 and initial_states: + for init_s in initial_states: + self.state_machine.add_transition( + trigger="", + source=f"{state_name}.{init_s}", + dest=f"{state_name}.{name}", + ) elif action_mode == "parallel": parallel_states.append(name) - if action_mode == "parallel": + if action_mode == "parallel" and not initial_states: machine_state.initial = parallel_states + elif action_mode == "parallel" and initial_states: + for init_s in initial_states: + for ps in parallel_states: + self.state_machine.add_transition( + trigger="", + source=f"{state_name}.{init_s}", + dest=f"{state_name}.{ps}", + ) def get_action_function(self, state: NestedState, f_name: str): if self.workflow.functions: @@ -461,13 +542,14 @@ def get_action_function(self, state: NestedState, f_name: str): state.metadata = {"function": current_function} break - def get_action_event(self, state: NestedState, e_name: str): + def get_action_event(self, state: NestedState, e_name: str, er_name: str = ""): if self.workflow.events: for event in self.workflow.events: current_event = event.serialize().__dict__ if current_event["name"] == e_name: state.metadata = {"event": current_event} - break + if current_event["name"] == er_name: + state.metadata = {"result_event": current_event} def subflow_state_name(self, action: Action, subflow: Workflow): return ( diff --git a/serverlessworkflow/sdk/state_machine_helper.py b/serverlessworkflow/sdk/state_machine_helper.py index cefeb69..9436d93 100644 --- a/serverlessworkflow/sdk/state_machine_helper.py +++ b/serverlessworkflow/sdk/state_machine_helper.py @@ -1,13 +1,10 @@ from typing import List from serverlessworkflow.sdk.workflow import Workflow from serverlessworkflow.sdk.state_machine_generator import StateMachineGenerator -from transitions.extensions.diagrams import HierarchicalGraphMachine, GraphMachine from serverlessworkflow.sdk.state_machine_extensions import ( CustomGraphMachine, CustomHierarchicalGraphMachine, ) -from transitions.extensions.nesting import NestedState -from transitions.extensions.diagrams_base import BaseGraph class StateMachineHelper:
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: