def create_decisions_from_flow(self, decisions, activity_states, context): """Create the decisions from the flow. Simple flows don't need a custom decider, since all the requirements can be provided at the activity level. Discovery of the next activity to schedule is thus very straightforward. Args: decisions (Layer1Decisions): the layer decision for swf. activity_states (dict): all the state activities. context (dict): the context of the activities. """ try: for current in activity.find_available_activities( self.flow, activity_states, context.current): schedule_activity_task(decisions, current, version=self.version) else: activities = list( activity.find_uncomplete_activities( self.flow, activity_states, context.current)) if not activities: decisions.complete_workflow_execution() except Exception as e: decisions.fail_workflow_execution(reason=str(e)) if self.on_exception: self.on_exception(self, e) self.logger.error(e, exc_info=True)
def create_decisions_from_flow(self, decisions, activity_states, context): """Create the decisions from the flow. Simple flows don't need a custom decider, since all the requirements can be provided at the activity level. Discovery of the next activity to schedule is thus very straightforward. Args: decisions (Layer1Decisions): the layer decision for swf. activity_states (dict): all the state activities. context (dict): the context of the activities. """ try: for current in activity.find_available_activities( self.flow, activity_states, context.current): schedule_activity_task( decisions, current, version=self.version) else: activities = list( activity.find_uncomplete_activities( self.flow, activity_states, context.current)) if not activities: decisions.complete_workflow_execution() except Exception as e: decisions.fail_workflow_execution(reason=str(e)) if self.on_exception: self.on_exception(self, e) self.logger.error(e, exc_info=True)
def test_activity_launch_sequence(): """Test available activities. """ from tests.fixtures.flows import example # First available activity is the activity_1. history = event.activity_states_from_events(decider.history[:1]) activities = list(activity.find_available_activities(example, history)) uncomplete = list(activity.find_uncomplete_activities(example, history)) assert len(activities) == 1 assert len(uncomplete) == 4 assert activities[0] == example.activity_1 # In between activities should not launch activities. history = event.activity_states_from_events(decider.history[:5]) activities = list(activity.find_available_activities(example, history)) uncomplete = list(activity.find_uncomplete_activities(example, history)) assert len(activities) == 0 assert len(uncomplete) == 4 # Two activities are launched in parallel: 2 and 3. history = event.activity_states_from_events(decider.history[:7]) activities = list(activity.find_available_activities(example, history)) uncomplete = list(activity.find_uncomplete_activities(example, history)) assert len(activities) == 2 assert example.activity_1 not in uncomplete # Activity 3 completes before activity 2. Activity 4 depends on 2 and 3 to # complete. history = event.activity_states_from_events(decider.history[:14]) activities = list(activity.find_available_activities(example, history)) uncomplete = list(activity.find_uncomplete_activities(example, history)) assert len(activities) == 0 assert example.activity_3 not in uncomplete # Activity 2 - 3 completed. history = event.activity_states_from_events(decider.history[:22]) activities = list(activity.find_available_activities(example, history)) uncomplete = list(activity.find_uncomplete_activities(example, history)) assert len(activities) == 1 assert activities[0] == example.activity_4 assert example.activity_1 not in uncomplete assert example.activity_2 not in uncomplete assert example.activity_3 not in uncomplete # Close history = event.activity_states_from_events(decider.history[:25]) activities = list(activity.find_available_activities(example, history)) uncomplete = list(activity.find_uncomplete_activities(example, history)) assert not activities assert not uncomplete
def run(self): """Run the decider. The decider defines which task needs to be launched and when based on the list of events provided. It looks at the list of all the available activities, and launch the ones that: * are not been scheduled yet. * have all the dependencies resolved. If the decider is not able to find an uncompleted activity, the workflow can safely mark its execution as complete. """ pool = self.poll() if not 'events' in pool: return history = self.get_history(pool) activity_states = self.get_activity_states(history) context = event.get_current_context(history) decisions = swf.Layer1Decisions() for current in activity.find_available_activities( self.flow, activity_states): decisions.schedule_activity_task( '%s-%i' % (current.name, time.time()), current.name, self.version, task_list=current.task_list, input=json.dumps(context)) else: activities = list( activity.find_uncomplete_activities( self.flow, activity_states)) if not activities: decisions.complete_workflow_execution() self.complete(decisions=decisions) return True