def test_raising_child_workflows(self): child_tasklist = self.task_list + '_child' wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, MasterWorkflowWithException) child_wf_worker = WorkflowWorker( self.session, self.region, self.domain, child_tasklist, RaisingChildWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = MasterWorkflowWithException.execute(child_tasklist) self.workflow_execution = instance.workflow_execution wf_worker.run_once() wf_worker.run_once() child_wf_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() assert len(hist) == 14 assert hist[-1]['eventType'] == 'WorkflowExecutionCompleted' assert self.serializer.loads(hist[-1]['workflowExecutionCompletedEventAttributes']['result']) == 2
def test_two_workflows(self): wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, MasterWorkflow, ChildWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = MasterWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution for i in range(3): wf_worker.run_once() act_worker.run_once() for i in range(2): wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 14) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 3)
def test_one_activity(self): wf_worker = MultiprocessingWorkflowExecutor(WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneActivityWorkflow)) act_worker = MultiprocessingActivityExecutor(ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities())) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.start() act_worker.start() time.sleep(20) act_worker.stop() wf_worker.stop() act_worker.join() wf_worker.join() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 3)
def test_one_activity_options_overrides_priority(self): class OneActivityWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): with activity_options(task_priority=66): arg_sum = yield BunchOfActivities.sum(arg1, arg2) return_(arg_sum) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneActivityWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[4]['activityTaskScheduledEventAttributes']['taskPriority'], '66')
def test_one_activity(self): class OneActivityWorkflow(WorkflowDefinition): def __init__(self, workflow_execution): super(OneActivityWorkflow, self).__init__(workflow_execution) self.activities_client = BunchOfActivities() @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): arg_sum = yield self.activities_client.sum(arg1, arg2) return_(arg_sum) wf_worker = GenericWorkflowWorker( self.session, self.region, self.domain, self.task_list, WorkflowFinder(OneActivityWorkflow)) self._register_workflows(wf_worker) act_worker = ThreadedActivityExecutor(ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities())) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.start(1, 4) act_worker.stop() wf_worker.run_once() act_worker.join() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 3)
def test_two_workflows_priority(self): wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, MasterWorkflowWithPriority, ChildWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = MasterWorkflowWithPriority.execute(arg1=1, arg2=2, priority=100) self.workflow_execution = instance.workflow_execution for i in range(3): wf_worker.run_once() act_worker.run_once() for i in range(2): wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 14) self.assertEqual(hist[4]['eventType'], 'StartChildWorkflowExecutionInitiated') self.assertEqual( hist[4]['startChildWorkflowExecutionInitiatedEventAttributes'] ['taskPriority'], '100')
def test_signalled_many_input_workflow(self): wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, SignalledManyInputWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SignalledManyInputWorkflow.execute() self.workflow_execution = instance.workflow_execution # wait and signal the workflow for i in range(1, 5): instance.add_data(i) instance.add_data(None) # stop looping wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 10) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), [1, 2, 3, 4])
def test_next_page_token_activities(self): # process over a hundred events, so that we're clear we can work with nextPageToken class NextPageTokenWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, repeat, arg1): for i in range(repeat): yield BunchOfActivities.sum(i, arg1) return_(repeat) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, NextPageTokenWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = NextPageTokenWorkflow.execute(repeat=21, arg1=1) self.workflow_execution = instance.workflow_execution for i in range(21): wf_worker.run_once() act_worker.run_once() wf_worker.run_once() # finish off time.sleep(1) hist, token = self.get_workflow_execution_history_with_token() events = hist hist = self.get_workflow_execution_history(next_page_token=token) events.extend(hist) self.assertEqual(len(events), 131) self.assertEqual(events[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( events[-1]['workflowExecutionCompletedEventAttributes']['result']), 21)
def test_all_future_activities(self): class AllFutureWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): sum_future = BunchOfActivities.sum(arg1, arg2) mul_future = BunchOfActivities.mul(arg1, arg2) result = yield sum_future, mul_future return_(result) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, AllFutureWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = AllFutureWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.run_once() wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 17) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), (3, 2))
def test_one_activity_dynamic(self): class OneActivityTimedWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): # create an activity call dynamically sum = flow_types.ActivityType('1.1', name='BunchOfActivities.sum') arg_sum = yield sum(arg1, arg2) return_(arg_sum) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneActivityTimedWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityTimedWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 3)
def test_workflow_continue_as_new(self): class NoActivitiesWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1): if arg1 > 0: arg1 -= 1 self.execute(arg1) else: return "TestExecution" worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, NoActivitiesWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = NoActivitiesWorkflow.execute(arg1=1) self.workflow_execution = instance.workflow_execution for i in range(2): worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionContinuedAsNew') new_run_id = hist[-1]['workflowExecutionContinuedAsNewEventAttributes']['newExecutionRunId'] hist = self.get_workflow_execution_history(run_id=new_run_id) self.assertEqual(len(hist), 5) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 'TestExecution')
def test_raising_child_workflows(self): child_tasklist = self.task_list + '_child' wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, MasterWorkflowWithException) child_wf_worker = WorkflowWorker(self.session, self.region, self.domain, child_tasklist, RaisingChildWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = MasterWorkflowWithException.execute(child_tasklist) self.workflow_execution = instance.workflow_execution wf_worker.run_once() wf_worker.run_once() child_wf_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() assert len(hist) == 14 assert hist[-1]['eventType'] == 'WorkflowExecutionCompleted' assert self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']) == 2
def test_one_activity_timed(self): class OneActivityTimedWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): mytime = workflow_time.time() yield BunchOfActivities.sum(arg1, arg2) return_([mytime, workflow_time.time()]) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneActivityTimedWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityTimedWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), [ int(time.mktime(hist[2]['eventTimestamp'].timetuple())), int(time.mktime(hist[8]['eventTimestamp'].timetuple()))])
def test_two_workflows(self): wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, MasterWorkflow, ChildWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = MasterWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution for i in range(3): wf_worker.run_once() act_worker.run_once() for i in range(2): wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 14) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), 3)
def test_signalled_workflow(self): wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, SignalledWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SignalledWorkflow.execute() self.workflow_execution = instance.workflow_execution # wait and signal the workflow time.sleep(1) instance.signal("Signaled") for i in range(2): wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), 'Signaled')
def test_no_activities_failure(self): class NoActivitiesFailureWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1): raise RuntimeError("ExecutionFailed") worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, NoActivitiesFailureWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list) as starter: instance = NoActivitiesFailureWorkflow.execute(arg1="TestExecution") self.workflow_execution = instance.workflow_execution worker.run_once() time.sleep(1) try: starter.wait_for_completion(instance, 1) except WorkflowFailedError as err: self.assertEqual(RuntimeError, type(err.cause)) else: self.fail("Should never succeed") hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionFailed') self.assertEqual(str(self.serializer.loads( hist[-1]['workflowExecutionFailedEventAttributes']['details'])[0]), "ExecutionFailed")
def test_no_activities_with_state(self): class NoActivitiesWorkflow(WorkflowDefinition): @execute(version='1.2', execution_start_to_close_timeout=60) def execute(self, arg1): self.workflow_state = "Workflow Started" return_(arg1) worker = ThreadedWorkflowExecutor(WorkflowWorker( self.session, self.region, self.domain, self.task_list, NoActivitiesWorkflow)) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = NoActivitiesWorkflow.execute(arg1="TestExecution") self.workflow_execution = instance.workflow_execution # start + stop should run the worker's Decider once worker.start() worker.stop() worker.join() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( hist[-2]['decisionTaskCompletedEventAttributes']['executionContext'], 'Workflow Started') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 'TestExecution')
def test_subclassed_workflow_multiver(self): class MultiverWorkflow(WorkflowDefinition): @execute(version='1.0', execution_start_to_close_timeout=60) def start_wf(self): pass @workflow(name='MultiverWorkflow') class SubMultiverWorkflow(MultiverWorkflow): @execute(version='1.1', execution_start_to_close_timeout=60) def start_wf(self): pass @execute(version='1.2', execution_start_to_close_timeout=60) def start_wf_v2(self): pass worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, SubMultiverWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SubMultiverWorkflow.start_wf() self.workflow_execution = instance.workflow_execution worker.run_once() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SubMultiverWorkflow.start_wf_v2() self.workflow_execution = instance.workflow_execution worker.run_once() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual({ 'name': 'MultiverWorkflow', 'version': '1.2' }, hist[0]['workflowExecutionStartedEventAttributes']['workflowType'])
def test_one_manual_one_automatic_activity(self): swf_client = self.client class OneManualOneAutomaticActivityWorkflow(WorkflowDefinition): def __init__(self, workflow_execution): super(OneManualOneAutomaticActivityWorkflow, self).__init__(workflow_execution) @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, template): (x, y) = yield ManualActivities.perform_task(template=template) arg_sum = yield BunchOfActivities.sum(x, y) return_(arg_sum) wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, OneManualOneAutomaticActivityWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, BunchOfActivities(), ManualActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneManualOneAutomaticActivityWorkflow.execute( template='instructions.tmpl') self.workflow_execution = instance.workflow_execution def complete_this_activity(): activities_client = ManualActivityCompletionClient(swf_client) with open('task_token.txt', 'r') as shared_file: task_token = shared_file.read() os.remove('task_token.txt') activities_client.complete((3, 4), task_token) wf_worker.run_once() act_worker.run_once() time.sleep(5) activity_finisher = Thread(target=complete_this_activity) activity_finisher.start() activity_finisher.join() wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 17) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), 7)
def test_subclassed_workflow_multiver(self): class MultiverWorkflow(WorkflowDefinition): @execute(version='1.0', execution_start_to_close_timeout=60) def start_wf(self): pass @workflow(name='MultiverWorkflow') class SubMultiverWorkflow(MultiverWorkflow): @execute(version='1.1', execution_start_to_close_timeout=60) def start_wf(self): pass @execute(version='1.2', execution_start_to_close_timeout=60) def start_wf_v2(self): pass worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, SubMultiverWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SubMultiverWorkflow.start_wf() self.workflow_execution = instance.workflow_execution worker.run_once() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SubMultiverWorkflow.start_wf_v2() self.workflow_execution = instance.workflow_execution worker.run_once() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual({'name': 'MultiverWorkflow', 'version': '1.2'}, hist[0] ['workflowExecutionStartedEventAttributes'] ['workflowType'])
def test_cancel_external_execution_success(self): class ExternalExecutionCancelTargetWorkflow(WorkflowDefinition): def __init__(self, workflow_execution): super(ExternalExecutionCancelTargetWorkflow, self).__init__( workflow_execution) self.activities_client = BunchOfActivities() @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self): yield self.activities_client.sleep_activity(30) return_(True) class ExternalExecutionCancelSourceWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, target_wf_id, target_run_id): external_wf = WorkflowDefinition(WorkflowExecution(target_wf_id, target_run_id)) yield external_wf.cancel() return_('pass') source_wf = ExternalExecutionCancelSourceWorkflow target_wf = ExternalExecutionCancelTargetWorkflow source_wf_worker = WorkflowWorker( self.session, self.region, self.domain, 'source_task_list', source_wf, target_wf) target_wf_worker, target_act_worker = self.get_workers( [source_wf, target_wf]) target_execution = self.start_workflow(target_wf) with workflow_starter(self.session, self.region, self.domain, 'source_task_list'): instance = source_wf.execute(*target_execution) source_execution = instance.workflow_execution target_act_worker_thread = Thread(target=target_act_worker.run_once) target_act_worker_thread.start() target_wf_worker.run_once() # sched sleep act source_wf_worker.run_once() # make cancel request target_wf_worker.run_once() # receieve request; cancel self source_wf_worker.run_once() # resolve cancel future; complete target_act_worker_thread.join() source_hist = self.get_workflow_execution_history( workflow_id=source_execution.workflow_id, run_id=source_execution.run_id) self.assertEqual(source_hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( source_hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 'pass') self.assertEqual(len(source_hist), 10) target_hist = self.get_workflow_execution_history( workflow_id=target_execution.workflow_id, run_id=target_execution.run_id) self.assertEqual(target_hist[-1]['eventType'], 'WorkflowExecutionCanceled') target_act_cancel_event = self.get_events(target_hist, 'ActivityTaskCancelRequested') self.assertEqual(len(target_act_cancel_event), 1)
def main(config_filename='config.ini'): config = configparser.ConfigParser() if os.path.isfile(config_filename): config.read(config_filename) else: print("Cannot file config file: {}".format(config_filename)) sys.exit(1) PROFILE = config.get('default', 'profile', fallback=None) REGION = config.get('default', 'region', fallback='us-east-1') DOMAIN = config.get('default', 'domain', fallback=None) TASKLIST = config.get('default', 'tasklist', fallback=None) if not DOMAIN or not TASKLIST: print("You must define a domain and tasklist in config.ini") sys.exit(1) if PROFILE: session = botocore.session.Session(profile=PROFILE) else: session = botocore.session.get_session() # Create decider # Registers workflowtype decider = workflow_worker.WorkflowWorker(session, REGION, DOMAIN, TASKLIST, HelloWorldWorkflow) # Create worker # Registers activities worker = activity_worker.ActivityWorker(session, REGION, DOMAIN, TASKLIST, HelloWorldActivities()) # Now that all workflow and activies are registered initialize the # workflow with workflow_starter(session, REGION, DOMAIN, TASKLIST): print("Workflow started") HelloWorldWorkflow.hello_world() # starts the workflow print("Fire decider") decider.run_once() print("Fire worker") worker.run_once() print("Fire decider again") decider.run_once() print("Fire worker again") worker.run_once() print("Fire decider to complete workflow") decider.run_once()
def test_try_except_with_timer(self): class TryExceptFinallyWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): @coroutine def do_try_except(): arg_sum = 0 try: arg_sum += yield BunchOfActivities.sum(arg1, arg2) yield BunchOfActivities.throw() except ActivityTaskFailedError as err: if isinstance(err.cause, ValueError) \ and str(err.cause) == 'Hello-Error': if err.event_id != 13 or err.activity_id != '2': raise RuntimeError("Test Failed") arg_sum += yield BunchOfActivities.sum(arg1, arg2) yield workflow_time.sleep(1) return_(arg_sum) result = yield do_try_except() return_(result) wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, TryExceptFinallyWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = TryExceptFinallyWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution for i in range(3): wf_worker.run_once() act_worker.run_once() # Once for the timer wf_worker.run_once() # Once for the completion wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 28) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), 6)
def test_one_manual_one_automatic_activity(self): swf_client = self.client class OneManualOneAutomaticActivityWorkflow(WorkflowDefinition): def __init__(self, workflow_execution): super(OneManualOneAutomaticActivityWorkflow, self).__init__(workflow_execution) @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, template): (x, y) = yield ManualActivities.perform_task(template=template) arg_sum = yield BunchOfActivities.sum(x, y) return_(arg_sum) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneManualOneAutomaticActivityWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities(), ManualActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneManualOneAutomaticActivityWorkflow.execute(template='instructions.tmpl') self.workflow_execution = instance.workflow_execution def complete_this_activity(): activities_client = ManualActivityCompletionClient(swf_client) with open('task_token.txt', 'r') as shared_file: task_token = shared_file.read() os.remove('task_token.txt') activities_client.complete((3,4), task_token) wf_worker.run_once() act_worker.run_once() time.sleep(5) activity_finisher = Thread(target=complete_this_activity) activity_finisher.start() activity_finisher.join() wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 17) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 7)
def test_try_except_with_timer(self): class TryExceptFinallyWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): @coroutine def do_try_except(): arg_sum = 0 try: arg_sum += yield BunchOfActivities.sum(arg1, arg2) yield BunchOfActivities.throw() except ActivityTaskFailedError as err: if isinstance(err.cause, ValueError) \ and str(err.cause) == 'Hello-Error': if err.event_id != 13 or err.activity_id != '2': raise RuntimeError("Test Failed") arg_sum += yield BunchOfActivities.sum(arg1, arg2) yield workflow_time.sleep(1) return_(arg_sum) result = yield do_try_except() return_(result) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, TryExceptFinallyWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = TryExceptFinallyWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution for i in range(3): wf_worker.run_once() act_worker.run_once() # Once for the timer wf_worker.run_once() # Once for the completion wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 28) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 6)
def test_activity_exception_retries(self): class ActivityRetryOnExceptionWorkflow(WorkflowDefinition): @execute(version='1.2', execution_start_to_close_timeout=60) def execute(self): try: yield RetryingActivities.activity_raises_errors(RuntimeError) except ActivityTaskFailedError as err: assert isinstance(err.cause, RuntimeError) try: yield RetryingActivities.activity_raises_errors(AttributeError) except ActivityTaskFailedError as err: assert isinstance(err.cause, AttributeError) pass wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, ActivityRetryOnExceptionWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, RetryingActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = ActivityRetryOnExceptionWorkflow.execute() self.workflow_execution = instance.workflow_execution for i in range(2): wf_worker.run_once() act_worker.run_once() # for the timer wf_worker.run_once() act_worker.run_once() wf_worker.run_once() # wf_worker.run_once() # print 'wfrun' time.sleep(1) # check that we have a timer started and that the workflow length is the same to validate # that retries happened only on one of the exceptions hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 28) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(hist[10]['eventType'], 'TimerStarted') self.assertEqual(hist[10]['timerStartedEventAttributes']['startToFireTimeout'], "0")
def test_two_workflows(self): wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneMultiWorkflow, TwoMultiWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneMultiWorkflow.execute(arg1=1, arg2=2) self.workflow_executions.append(instance.workflow_execution) instance = TwoMultiWorkflow.execute(arg1=1, arg2=2) self.workflow_executions.append(instance.workflow_execution) for i in range(2): wf_worker.run_once() act_worker.run_once() wf_worker.run_once() wf_worker.run_once() time.sleep(1)
def test_no_activities(self): worker = MultiprocessingWorkflowExecutor(WorkflowWorker( self.session, self.region, self.domain, self.task_list, NoActivitiesWorkflow)) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = NoActivitiesWorkflow.execute(arg1="TestExecution") self.workflow_execution = instance.workflow_execution # start + stop should run the worker's Decider once worker.start() worker.stop() worker.join() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 'TestExecution')
def test_one_activity_default_task_list(self): class OneActivityCustomTaskList(object): @activity(version='1.1', task_list='abracadabra') def sum(self, x, y): return x + y class OneActivityDefaultTaskListWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): arg_sum = yield OneActivityCustomTaskList.sum(arg1, arg2) return_(arg_sum) wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, OneActivityDefaultTaskListWorkflow) act_worker = ThreadedActivityExecutor( ActivityWorker(self.session, self.region, self.domain, 'abracadabra', OneActivityCustomTaskList())) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityDefaultTaskListWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.start(1, 4) act_worker.stop() wf_worker.run_once() act_worker.join() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual( hist[4]['activityTaskScheduledEventAttributes']['taskList'] ['name'], 'abracadabra') self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), 3)
def test_no_activities_failure(self): worker = MultiprocessingWorkflowExecutor(WorkflowWorker( self.session, self.region, self.domain, self.task_list, NoActivitiesFailureWorkflow)) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = NoActivitiesFailureWorkflow.execute(arg1="TestExecution") self.workflow_execution = instance.workflow_execution worker.start() worker.stop() worker.join() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionFailed') self.assertEqual(str(self.serializer.loads( hist[-1]['workflowExecutionFailedEventAttributes']['details'])[0]), "ExecutionFailed")
def test_child_workflow_timed_out(self): wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, TimingOutMasterWorkflow, TimingOutChildWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = TimingOutMasterWorkflow.execute() self.workflow_execution = instance.workflow_execution wf_worker.run_once() time.sleep(3) wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 1)
def test_two_workflows(self): wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, OneMultiWorkflow, TwoMultiWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneMultiWorkflow.execute(arg1=1, arg2=2) self.workflow_executions.append(instance.workflow_execution) instance = TwoMultiWorkflow.execute(arg1=1, arg2=2) self.workflow_executions.append(instance.workflow_execution) for i in range(2): wf_worker.run_once() act_worker.run_once() wf_worker.run_once() wf_worker.run_once() time.sleep(1)
def test_one_activity_default_task_list(self): class OneActivityCustomTaskList(object): @activity(version='1.1', task_list='abracadabra') def sum(self, x, y): return x + y class OneActivityDefaultTaskListWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): arg_sum = yield OneActivityCustomTaskList.sum(arg1, arg2) return_(arg_sum) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneActivityDefaultTaskListWorkflow) act_worker = ThreadedActivityExecutor(ActivityWorker( self.session, self.region, self.domain, 'abracadabra', OneActivityCustomTaskList())) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityDefaultTaskListWorkflow.execute( arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.start(1, 4) act_worker.stop() wf_worker.run_once() act_worker.join() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[4]['activityTaskScheduledEventAttributes'] ['taskList']['name'], 'abracadabra') self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 3)
def test_subclassed_workflow_no_exec(self): class SuperClassWorkflow(WorkflowDefinition): @execute(version='1.0', execution_start_to_close_timeout=60) def execute(self): pass class SubClassWorkflow(SuperClassWorkflow): pass worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, SubClassWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SubClassWorkflow.execute() self.workflow_execution = instance.workflow_execution worker.run_once() time.sleep(2) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 5)
def test_one_activity_with_timer(self): class OneActivityWithTimerWorkflow(WorkflowDefinition): def __init__(self, workflow_execution): super(OneActivityWithTimerWorkflow, self).__init__(workflow_execution) self.activities_client = BunchOfActivities() @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): yield workflow_time.sleep(2) arg_sum = yield self.activities_client.sum(arg1, arg2) return_(arg_sum) wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, OneActivityWithTimerWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityWithTimerWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 16) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') # timer specific checks self.assertEqual(hist[4]['eventType'], 'TimerStarted') self.assertEqual( hist[4]['timerStartedEventAttributes']['startToFireTimeout'], '2') self.assertEqual(hist[5]['eventType'], 'TimerFired')
def test_any_future_activities(self): class SleepingActivities(object): @activity(version='1.2', schedule_to_start_timeout=60, start_to_close_timeout=60) def sleep(self, time_to_sleep): time.sleep(time_to_sleep) return time_to_sleep class AnyFutureWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): sleep1_future = SleepingActivities.sleep(arg1) sleep2_future = SleepingActivities.sleep(arg2) result = yield sleep1_future | sleep2_future return_(result) wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, AnyFutureWorkflow) act_worker = ActivityWorker(self.session, self.region, self.domain, self.task_list, SleepingActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = AnyFutureWorkflow.execute(arg1=5, arg2=1) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 14) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertTrue( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']))
def test_child_workflow_timed_out(self): wf_worker = WorkflowWorker(self.session, self.region, self.domain, self.task_list, TimingOutMasterWorkflow, TimingOutChildWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = TimingOutMasterWorkflow.execute() self.workflow_execution = instance.workflow_execution wf_worker.run_once() time.sleep(3) wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual( self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes'] ['result']), 1)
def test_any_future_activities(self): class SleepingActivities(object): @activity(version='1.2', schedule_to_start_timeout=60, start_to_close_timeout=60) def sleep(self, time_to_sleep): time.sleep(time_to_sleep) return time_to_sleep class AnyFutureWorkflow(WorkflowDefinition): @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): sleep1_future = SleepingActivities.sleep(arg1) sleep2_future = SleepingActivities.sleep(arg2) result = yield sleep1_future | sleep2_future return_(result) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, AnyFutureWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, SleepingActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = AnyFutureWorkflow.execute(arg1=5, arg2=1) self.workflow_execution = instance.workflow_execution wf_worker.run_once() act_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 14) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertTrue(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']))
def test_signalled_workflow(self): wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, SignalledWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SignalledWorkflow.execute() self.workflow_execution = instance.workflow_execution # wait and signal the workflow time.sleep(1) instance.signal("Signaled") for i in range(2): wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 11) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), 'Signaled')
def test_signalled_many_input_workflow(self): wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, SignalledManyInputWorkflow) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = SignalledManyInputWorkflow.execute() self.workflow_execution = instance.workflow_execution # wait and signal the workflow for i in range(1, 5): instance.add_data(i) instance.add_data(None) # stop looping wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 10) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(self.serializer.loads( hist[-1]['workflowExecutionCompletedEventAttributes']['result']), [1,2,3,4])
def test_activity_timeouts(self): class ActivityRetryOnTimeoutWorkflow(WorkflowDefinition): @execute(version='1.2', execution_start_to_close_timeout=60) def execute(self, sleep): try: yield RetryingActivities.activity_timing_out(sleep) except ActivityTaskTimedOutError: pass wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, ActivityRetryOnTimeoutWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, RetryingActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = ActivityRetryOnTimeoutWorkflow.execute(sleep=2) self.workflow_execution = instance.workflow_execution for i in range(2): wf_worker.run_once() try: act_worker.run_once() except swf_exceptions.UnknownResourceError: # we expect the activity to have timed out already pass # for the timer wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 22) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') self.assertEqual(hist[10]['eventType'], 'TimerStarted') self.assertEqual(hist[10]['timerStartedEventAttributes']['startToFireTimeout'], "1")
def test_one_activity_with_timer(self): class OneActivityWithTimerWorkflow(WorkflowDefinition): def __init__(self, workflow_execution): super(OneActivityWithTimerWorkflow, self).__init__(workflow_execution) self.activities_client = BunchOfActivities() @execute(version='1.1', execution_start_to_close_timeout=60) def execute(self, arg1, arg2): yield workflow_time.sleep(2) arg_sum = yield self.activities_client.sum(arg1, arg2) return_(arg_sum) wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, OneActivityWithTimerWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = OneActivityWithTimerWorkflow.execute(arg1=1, arg2=2) self.workflow_execution = instance.workflow_execution wf_worker.run_once() wf_worker.run_once() act_worker.run_once() wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 16) self.assertEqual(hist[-1]['eventType'], 'WorkflowExecutionCompleted') # timer specific checks self.assertEqual(hist[4]['eventType'], 'TimerStarted') self.assertEqual(hist[4]['timerStartedEventAttributes']['startToFireTimeout'], '2') self.assertEqual(hist[5]['eventType'], 'TimerFired')
def test_two_workflows_priority(self): wf_worker = WorkflowWorker( self.session, self.region, self.domain, self.task_list, MasterWorkflowWithPriority, ChildWorkflow) act_worker = ActivityWorker( self.session, self.region, self.domain, self.task_list, BunchOfActivities()) with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = MasterWorkflowWithPriority.execute(arg1=1, arg2=2, priority=100) self.workflow_execution = instance.workflow_execution for i in range(3): wf_worker.run_once() act_worker.run_once() for i in range(2): wf_worker.run_once() time.sleep(1) hist = self.get_workflow_execution_history() self.assertEqual(len(hist), 14) self.assertEqual(hist[4]['eventType'], 'StartChildWorkflowExecutionInitiated') self.assertEqual(hist[4]['startChildWorkflowExecutionInitiatedEventAttributes']['taskPriority'], '100')
def start_workflow(self, workflow_class, *args, **kwargs): with workflow_starter(self.session, self.region, self.domain, self.task_list): instance = workflow_class.execute(*args, **kwargs) self.workflow_execution = instance.workflow_execution return instance.workflow_execution