コード例 #1
0
ファイル: executor.py プロジェクト: zenefits/simpleflow
    def replay(self, history):
        """Executes the workflow from the start until it blocks.

        """
        self.reset()

        self._history = History(history)
        self._history.parse()

        workflow_started_event = history[0]
        args = ()
        kwargs = {}
        input = workflow_started_event.input
        if input is None:
            input = {}
        args = input.get('args', ())
        kwargs = input.get('kwargs', {})

        # check if there is a workflow cancellation request
        if self._history.is_cancel_requested:
            # list all the running activities
            cancellable_activities_id = self._history.list_cancellable_activities()

            if len(cancellable_activities_id) == 0:
                # nothing to cancel, completing the workflow as cancelled
                cancel_decision = swf.models.decision.WorkflowExecutionDecision()
                cancel_decision.cancel()

                logger.info('Sucessfully canceled the workflow.')
                return [cancel_decision], {}

            cancel_activities_decisions = []
            for activity_id in cancellable_activities_id:
                # send cancel request to each of them
                decision = swf.models.decision.ActivityTaskDecision(
                    'request_cancel',
                    activity_id=activity_id,
                )

                cancel_activities_decisions.append(decision)

            return cancel_activities_decisions, {}

        # handle workflow on start delay
        if self._workflow.delayed_start_timer > 0:
            if 'delayed_start_timer' not in self._history._timers:
                logger.info('Scheduling delayed start decision.')
                timer = swf.models.decision.TimerDecision(
                        'start',
                        id='delayed_start_timer',
                        start_to_fire_timeout=str(self._workflow.delayed_start_timer))
                self._decisions.append(timer)
                return self._decisions, {}
            elif self._history._timers['delayed_start_timer']['state'] != 'fired':
                # wait for the timer event, no-op
                logger.info('Timer has not fired yet.')
                return [], {}

        if self._history.is_workflow_started:
            # the workflow has just started
            self.on_start(args, kwargs)

        # workflow not cancelled
        try:
            result = self.run_workflow(*args, **kwargs)
        except exceptions.ExecutionBlocked:
            logger.info('{} open activities ({} decisions)'.format(
                self._open_activity_count,
                len(self._decisions),
            ))
            return self._decisions, {}
        except exceptions.TaskException, err:
            reason = 'Workflow execution error in task {}: "{}"'.format(
                err.task.name,
                getattr(err.exception, 'reason', repr(err.exception)))
            logger.info(reason)

            details = getattr(err.exception, 'details', None)

            self.on_failure(reason, details, args, kwargs)

            decision = swf.models.decision.WorkflowExecutionDecision()
            if self._workflow.is_daemon:
                # do not fail daemon workflow
                logger.info('Task failed. Re-running continue_as_new for the daemon workflow.')
                decision.continue_as_new(
                    input=input,
                    task_list={ 'name': self.task_list },
                    task_timeout=str(self._workflow.decision_tasks_timeout),
                    execution_timeout=str(self._workflow.execution_timeout),
                    workflow_type_version=str(self._workflow.version))
            else:
                decision.fail(
                    reason=swf.format.reason(reason),
                    details=swf.format.details(details),
                )
            return [decision], {}
コード例 #2
0
ファイル: executor.py プロジェクト: zenefits/simpleflow
                # do not fail daemon workflow
                logger.info('Unexpected workflow error. Re-running continue_as_new for the daemon workflow.')
                decision.continue_as_new(input=input, task_list={ 'name': self.task_list }, task_timeout=str(self._workflow.decision_tasks_timeout))
            else:
                decision.fail(
                    reason=swf.format.reason(reason),
                    details=swf.format.details(details),
                )

            return [decision], {}

        decision = swf.models.decision.WorkflowExecutionDecision()
        if self._workflow.is_daemon:
            # do not complete daemon workflow
            logger.info('Running continue_as_new for the daemon workflow.')
            decision.continue_as_new(input=input, task_list={ 'name': self.task_list }, task_timeout=str(self._workflow.decision_tasks_timeout))
        else:
            decision.complete(result=swf.format.result(json.dumps(result)))

        self.on_complete(result, args, kwargs)

        return [decision], {}

    def on_start(self, wfargs=None, wfkwargs=None):
        try:
            self._workflow.on_start(wfargs, wfkwargs)
        except:
            logger.exception('Error executing on_start for workflow.', extra = { 'input_args': json.dumps(wfargs), 'input_kwargs': json.dumps(wfkwargs) })

    def on_complete(self, result, wfargs=None, wfkwargs=None):
        try: