def run(self, task_list): """Poll decision task from SWF and process. """ events = self.poll(task_list) if not events: return self.handler = StepHandler( events, activity_max_retry=config.ACTIVITY_MAX_RETRY, workflow_max_retry=config.WORKFLOW_MAX_RETRY) try: result = self.execute() if self.handler.is_waiting(): raise TaskWait except TaskWait: self.suspend() except TaskError: _, error, _ = sys.exc_info() self.fail(error.reason, error.details) except: _, error, _ = sys.exc_info() self.fail(repr(error), json.dumps(traceback.format_exc())) else: self.complete(result)
class SWFDecider(Decider): def run(self, task_list): """Poll decision task from SWF and process. """ events = self.poll(task_list) if not events: return self.handler = StepHandler( events, activity_max_retry=config.ACTIVITY_MAX_RETRY, workflow_max_retry=config.WORKFLOW_MAX_RETRY) try: result = self.execute() if self.handler.is_waiting(): raise TaskWait except TaskWait: self.suspend() except TaskError: _, error, _ = sys.exc_info() self.fail(error.reason, error.details) except: _, error, _ = sys.exc_info() self.fail(repr(error), json.dumps(traceback.format_exc())) else: self.complete(result) def execute(self): """Execute input of SWF workflow. """ type_ = 'Job' if 'Job' in self.handler.input else 'Task' parallel = self.handler.input[type_].get('parallel', False) for i, child in enumerate(self.handler.input[type_]['children']): priority = get_priority(self.handler.input, self.handler.priority, i) if 'Task' in child: self.execute_task(child, priority) elif 'Action' in child and not child['Action']['_whenerror']: self.execute_action(child, priority) if not parallel: self.wait() if parallel: for child in self.handler.input[type_]['children']: self.wait() def execute_task(self, task, priority): """Schedule task to SWF as child workflow and wait. If the task is not completed, raise TaskWait. """ if self.handler.is_waiting(): raise TaskWait elif self.handler.is_scheduled(): return else: handler = InputHandler(self.handler.protocol) ChildWorkflowExecution.start( decisions=self.decisions, name=self.handler.get_next_workflow_name(task['Task']['title']), input_data={ 'protocol': self.handler.protocol, 'body': handler.save( data=task, genealogy=self.handler.tag_list + [task['Task']['title']]) }, tag_list=self.handler.tag_list + [task['Task']['title']], priority=priority) def execute_action(self, action, priority): """Schedule action to SWF as activity task and wait. If action is not completed, raise TaskWait. """ if self.handler.is_waiting(): raise TaskWait elif self.handler.is_scheduled(): return else: handler = InputHandler(self.handler.protocol) action_name = self.handler.get_next_activity_name() ActivityTask.schedule( self.decisions, name=action_name, input_data={ 'protocol': self.handler.protocol, 'body': handler.save( data=action, genealogy=self.handler.tag_list + ['Action%s' % action_name]) }, task_list=action['Action'].get('_role', config.ACTIVITY_TASK_LIST), priority=priority ) def fail(self, reason, details): try: type_ = 'Job' if 'Job' in self.handler.input else 'Task' actions = filter(lambda c: 'Action' in c, self.handler.input[type_]['children']) for i, child in enumerate(self.handler.input[type_]['children']): if 'Action' not in child: continue if child['Action']['_whenerror'] is False: continue priority = get_priority(self.handler.input, self.handler.priority, i) self.execute_action(child, priority) self.wait() except TaskWait: self.suspend() except TaskError: _, error, _ = sys.exc_info() super(SWFDecider, self).fail( error.reason[:config.MAX_REASON_SIZE] if error.reason else error.reason, error.details[:config.MAX_DETAIL_SIZE] if error.details else error.details) except: _, error, _ = sys.exc_info() super(SWFDecider, self).fail( repr(error)[:config.MAX_REASON_SIZE], traceback.format_exc()[:config.MAX_DETAIL_SIZE]) else: super(SWFDecider, self).fail( reason[:config.MAX_REASON_SIZE] if reason else reason, details[:config.MAX_DETAIL_SIZE] if details else details) def wait(self): """Check if the next step could be processed. If the previous step is submitted to SWF, processed and successful, return result. """ if self.decisions._data: raise TaskWait with self.handler.pop() as step: if not step: return if step.status() in ['Failed', 'TimedOut']: if step.should_retry(): step.retry(self.decisions) raise TaskWait else: error = step.error() step.is_checked = True raise TaskError(error.reason, error.details) else: return step.result()
class SWFDecider(Decider): def run(self, task_list): """Poll decision task from SWF and process. """ events = self.poll(task_list) if not events: return self.handler = StepHandler( events, activity_max_retry=config.ACTIVITY_MAX_RETRY, workflow_max_retry=config.WORKFLOW_MAX_RETRY) try: result = self.execute() if self.handler.is_waiting(): raise TaskWait except TaskWait: self.suspend() except TaskError: _, error, _ = sys.exc_info() self.fail(error.reason, error.details) except: _, error, _ = sys.exc_info() self.fail(repr(error), json.dumps(traceback.format_exc())) else: self.complete(result) def execute(self): """Execute input of SWF workflow. """ type_ = 'Job' if 'Job' in self.handler.input else 'Task' parallel = self.handler.input[type_].get('parallel', False) for i, child in enumerate(self.handler.input[type_]['children']): priority = get_priority(self.handler.input, self.handler.priority, i) if 'Task' in child: self.execute_task(child, priority) elif 'Action' in child and not child['Action']['_whenerror']: self.execute_action(child, priority) if not parallel: self.wait() if parallel: for child in self.handler.input[type_]['children']: self.wait() def execute_task(self, task, priority): """Schedule task to SWF as child workflow and wait. If the task is not completed, raise TaskWait. """ if self.handler.is_waiting(): raise TaskWait elif self.handler.is_scheduled(): return else: handler = InputHandler(self.handler.protocol) ChildWorkflowExecution.start( decisions=self.decisions, name=self.handler.get_next_workflow_name( task['Task']['title']), input_data={ 'protocol': self.handler.protocol, 'body': handler.save(data=task, genealogy=self.handler.tag_list + [task['Task']['title']]) }, tag_list=self.handler.tag_list + [task['Task']['title']], priority=priority) def execute_action(self, action, priority): """Schedule action to SWF as activity task and wait. If action is not completed, raise TaskWait. """ if self.handler.is_waiting(): raise TaskWait elif self.handler.is_scheduled(): return else: handler = InputHandler(self.handler.protocol) action_name = self.handler.get_next_activity_name() ActivityTask.schedule( self.decisions, name=action_name, input_data={ 'protocol': self.handler.protocol, 'body': handler.save(data=action, genealogy=self.handler.tag_list + ['Action%s' % action_name]) }, task_list=action['Action'].get('_role', config.ACTIVITY_TASK_LIST), priority=priority) def fail(self, reason, details): try: type_ = 'Job' if 'Job' in self.handler.input else 'Task' actions = filter(lambda c: 'Action' in c, self.handler.input[type_]['children']) for i, child in enumerate(self.handler.input[type_]['children']): if 'Action' not in child: continue if child['Action']['_whenerror'] is False: continue priority = get_priority(self.handler.input, self.handler.priority, i) self.execute_action(child, priority) self.wait() except TaskWait: self.suspend() except TaskError: _, error, _ = sys.exc_info() super(SWFDecider, self).fail( error.reason[:config.MAX_REASON_SIZE] if error.reason else error.reason, error.details[:config.MAX_DETAIL_SIZE] if error.details else error.details) except: _, error, _ = sys.exc_info() super(SWFDecider, self).fail( repr(error)[:config.MAX_REASON_SIZE], traceback.format_exc()[:config.MAX_DETAIL_SIZE]) else: super(SWFDecider, self).fail( reason[:config.MAX_REASON_SIZE] if reason else reason, details[:config.MAX_DETAIL_SIZE] if details else details) def wait(self): """Check if the next step could be processed. If the previous step is submitted to SWF, processed and successful, return result. """ if self.decisions._data: raise TaskWait with self.handler.pop() as step: if not step: return if step.status() in ['Failed', 'TimedOut']: if step.should_retry(): step.retry(self.decisions) raise TaskWait else: error = step.error() step.is_checked = True raise TaskError(error.reason, error.details) else: return step.result()