Example #1
0
    def signal(self, signal_name, input=None, workflow_id=None, run_id=None, *args, **kwargs):
        """Records a signal event in the workflow execution history and
        creates a decision task.

        The signal event is recorded with the specified user defined
        ``signal_name`` and ``input`` (if provided).

        Default to send to oneself (for compatibility with the previous versions).

        :param  signal_name: The name of the signal. This name must be
                             meaningful to the target workflow.
        :type   signal_name: str

        :param  input: Data to attach to the WorkflowExecutionSignaled
                       event in the target workflow execution’s history.
        :type   input: dict
        :param  workflow_id: Workflow ID to send the signal to.
        :type  workflow_id: str
        :param  run_id: Run ID to send the signal to.
        :type  run_id: str
        """
        if input is None:
            input = {}
        self.connection.signal_workflow_execution(
            self.domain.name,
            signal_name,
            workflow_id or self.workflow_id,
            input=format.input(input),
            run_id=run_id if workflow_id else self.run_id,
        )
Example #2
0
    def signal(self, signal_name, workflow_id, control=None, input=None, run_id=None):
        """Signal external workflow execution decision builder

        :param  signal_name: name of the signal
        :type   signal_name: str

        :param  workflow_id: workflow id of the workflow execution to be signaled
        :type   workflow_id: str


        :param  control: data attached to the event that can be used by the decider
                         in subsequent decision tasks
        :type   control: Optional[dict]

        :param  input: input to be provided with the signal
        :type   input: Optional[dict]

        :param  run_id: run id of the workflow execution to be signaled
        :type   run_id: str
        """
        if input is not None:
            input = format.input(input)
        if control is not None:
            control = format.control(control)

        self.update_attributes(
            {
                "signalName": signal_name,
                "workflowId": workflow_id,
                "control": control,
                "input": input,
                "runId": run_id,
            }
        )
Example #3
0
    def start_execution(self, workflow_id=None, task_list=None,
                        child_policy=None, execution_timeout=None,
                        input=None, tag_list=None, decision_tasks_timeout=None):
        """Starts a Workflow execution of current workflow type

        :param  workflow_id: The user defined identifier associated with the workflow execution
        :type   workflow_id: String

        :param  task_list: task list to use for scheduling decision tasks for execution
                        of this workflow
        :type   task_list: String

        :param  child_policy: policy to use for the child workflow executions
                              of this workflow execution.
        :type   child_policy: CHILD_POLICIES.{TERMINATE |
                                              REQUEST_CANCEL |
                                              ABANDON}

        :param  execution_timeout: maximum duration for the workflow execution
        :type   execution_timeout: String

        :param  input: Input of the workflow execution
        :type   input: dict

        :param  tag_list: Tags associated with the workflow execution
        :type   tag_list: String or list of strings or None

        :param  decision_tasks_timeout: maximum duration of decision tasks
                                        for this workflow execution
        :type   decision_tasks_timeout: String
        """
        workflow_id = workflow_id or '%s-%s-%i' % (self.name, self.version, time.time())
        task_list = task_list or self.task_list
        child_policy = child_policy or self.child_policy
        if child_policy not in CHILD_POLICIES:
            raise ValueError("invalid child policy value: {}".format(child_policy))
        if input is None:
            input = {}
        if tag_list is not None and not isinstance(tag_list, list):
            tag_list = [tag_list]

        # checks
        if tag_list and len(tag_list) > 5:
            raise ValueError("You cannot have more than 5 tags in StartWorkflowExecution.")

        run_id = self.connection.start_workflow_execution(
            self.domain.name,
            workflow_id,
            self.name,
            self.version,
            task_list=task_list,
            child_policy=child_policy,
            execution_start_to_close_timeout=execution_timeout,
            input=format.input(input),
            tag_list=tag_list,
            task_start_to_close_timeout=decision_tasks_timeout,
        )['runId']

        return WorkflowExecution(self.domain, workflow_id, run_id=run_id)
Example #4
0
    def start(self,
              workflow_type,
              workflow_id,
              child_policy=CHILD_POLICIES.TERMINATE,
              execution_timeout='300',
              task_timeout='300',
              control=None,
              input=None,
              tag_list=None,
              task_list=None):
        """Child workflow execution decision builder

        :param  workflow_type: workflow type to start
        :type   workflow_type: swf.models.workflow.WorkflowType

        :param  workflow_id: unique id to recognize the workflow execution
        :type   workflow_id: str

        :param  child_policy: specifies the policy to use for the
                              child workflow executions
        :type   child_policy: CHILD_POLICIES.{TERMINATE | REQUEST_CANCEL | ABANDON}

        :param  execution_timeout: specifies the total duration for this workflow execution
        :type   execution_timeout: str

        :param  input: The input provided to the child workflow execution
        :type   input: str

        :param  tag_list: list of tags to associate with the child workflow execution
        :type   tag_list: list

        :param  task_list: task list name
        :type   task_list: str

        :param  task_timeout: maximum duration of decision tasks for the child workflow execution
        :type   task_timeout: str

        """
        if input is not None:
            input = format.input(input)

        self.update_attributes({
            'childPolicy': child_policy,
            'executionStartToCloseTimeout': execution_timeout,
            'taskStartToCloseTimeout': task_timeout,
            'control': control,
            'input': input,
            'tagList': tag_list,
            'taskList': {
                'name': task_list,
            },
            'workflowId': workflow_id,
            'workflowType': {
                'name': workflow_type.name,
                'version': workflow_type.version,
            }
        })
Example #5
0
    def continue_as_new(
        self,
        child_policy=None,
        execution_timeout=None,
        task_timeout=None,
        input=None,
        tag_list=None,
        task_list=None,
        workflow_type_version=None,
    ):
        """Coninue as new workflow execution decision builder
        :param  child_policy: specifies the policy to use for the
                              child workflow executions of the new execution
        :type   child_policy: CHILD_POLICIES.{TERMINATE | REQUEST_CANCEL | ABANDON}

        :param  execution_timeout: specifies the total duration for this workflow execution
        :type   execution_timeout: str

        :param  input: The input provided to the new workflow execution
        :type   input: Optional[dict]

        :param  tag_list: list of tags to associate with the new workflow execution
        :type   tag_list: list

        :param  task_list: task list name
        :type   task_list: str

        :param  task_timeout: maximum duration of decision tasks for the new workflow execution
        :type   task_timeout: str

        :param  workflow_type_version: workflow type version the execution shold belong to
        :type   workflow_type_version: str
        """
        if input is not None:
            input = format.input(input)

        self.update_attributes(
            {
                "childPolicy": child_policy,
                "executionStartToCloseTimeout": execution_timeout,
                "taskStartToCloseTimeout": task_timeout,
                "input": input,
                "tagList": tag_list,
                "taskList": task_list,
                "workflowTypeVersion": workflow_type_version,
            }
        )
Example #6
0
    def schedule(self,
                 activity_id,
                 activity_type,
                 control=None,
                 heartbeat_timeout=None,
                 input=None,
                 duration_timeout=None,
                 schedule_timeout=None,
                 task_timeout=None,
                 task_list=None,
                 task_priority=None):
        """Schedule activity task decision builder

        :param  activity_id: activity id of the activity task
        :type   activity_id: String

        :param  activity_type: type of the activity task to schedule
        :type   activity_type: swf.models.activity.ActivityType

        :param  control: data attached to the event that can be used by the decider in subsequent workflow tasks
        :type   control: Optional[dict]

        :param  heartbeat_timeout: Specifies the maximum time before which a worker processing a task of this type must
                report progress
        :type   heartbeat_timeout: String

        :param  input: input provided to the activity task
        :type   input: Optional[dict]

        :param  duration_timeout: Maximum duration for this activity task
        :type   duration_timeout: String

        :param  schedule_timeout: Specifies the maximum duration the activity task can wait to be assigned to a worker
        :type   schedule_timeout: String

        :param  task_timeout: Specifies the maximum duration a worker may take to process this activity task
        :type   task_timeout: String

        :param  task_list: Specifies the name of the task list in which to schedule the activity task
        :type   :str

        :param  task_priority: Specifies the numeric priority of the task to pass to SWF (defaults to None).
        :type   task_priority: int|String
        """
        if input is not None:
            input = format.input(input)
        if control is not None:
            control = format.control(control)

        if task_priority is not None:
            # NB: here we call int() so we raise early if a wrong task priority
            # is passed to this function.
            task_priority = str(int(task_priority))

        self.update_attributes({
            'activityId': activity_id,
            'activityType': {
                'name': activity_type.name,
                'version': activity_type.version,
            },
            'control': control,
            'heartbeatTimeout': heartbeat_timeout,
            'input': input,
            'scheduleToCloseTimeout': duration_timeout,
            'scheduleToStartTimeout': schedule_timeout,
            'startToCloseTimeout': task_timeout,
            'taskList': {
                'name': task_list
            },
            'taskPriority': task_priority,
        })
Example #7
0
    def start(
        self,
        workflow_type,
        workflow_id,
        child_policy=CHILD_POLICIES.TERMINATE,
        execution_timeout="300",
        task_timeout="300",
        control=None,
        input=None,
        tag_list=None,
        task_list=None,
    ):
        """Child workflow execution decision builder

        :param  workflow_type: workflow type to start
        :type   workflow_type: swf.models.workflow.WorkflowType

        :param  workflow_id: unique id to recognize the workflow execution
        :type   workflow_id: str

        :param  child_policy: specifies the policy to use for the
                              child workflow executions
        :type   child_policy: CHILD_POLICIES.{TERMINATE | REQUEST_CANCEL | ABANDON}

        :param  execution_timeout: specifies the total duration for this workflow execution
        :type   execution_timeout: str

        :param  input: The input provided to the child workflow execution
        :type   input: Optional[dict]

        :param  tag_list: list of tags to associate with the child workflow execution
        :type   tag_list: list

        :param  task_list: task list name
        :type   task_list: str

        :param  task_timeout: maximum duration of decision tasks for the child workflow execution
        :type   task_timeout: str

        :param  control: data attached to the event that can be used by
                  the decider in subsequent workflow tasks
        :type   control: Optional[dict]

        """
        if input is not None:
            input = format.input(input)
        if control is not None:
            control = format.control(control)

        self.update_attributes(
            {
                "childPolicy": child_policy,
                "executionStartToCloseTimeout": execution_timeout,
                "taskStartToCloseTimeout": task_timeout,
                "control": control,
                "input": input,
                "tagList": tag_list,
                "taskList": {"name": task_list,},
                "workflowId": workflow_id,
                "workflowType": {
                    "name": workflow_type.name,
                    "version": workflow_type.version,
                },
            }
        )
Example #8
0
def standalone(
    context,
    workflow,
    domain,
    workflow_id,
    execution_timeout,
    tags,
    decision_tasks_timeout,
    input,
    input_file,
    nb_workers,
    nb_deciders,
    heartbeat,
    display_status,
    repair,
    force_activities,
):
    """
    This command spawn a decider and an activity worker to execute a workflow
    with a single main process.

    """
    disable_boto_connection_pooling()

    if force_activities and not repair:
        raise ValueError(
            "You should only use --force-activities with --repair.")

    workflow_class = get_workflow(workflow)
    if not workflow_id:
        workflow_id = workflow_class.name

    wf_input = {}
    if input or input_file:
        wf_input = get_or_load_input(input_file, input)

    if repair:
        repair_run_id = None
        if " " in repair:
            repair, repair_run_id = repair.split(" ", 1)
        # get the previous execution history, it will serve as "default history"
        # for activities that succeeded in the previous execution
        logger.info('retrieving history of previous execution: domain={} '
                    'workflow_id={} run_id={}'.format(domain, repair,
                                                      repair_run_id))
        workflow_execution = get_workflow_execution(domain,
                                                    repair,
                                                    run_id=repair_run_id)
        previous_history = History(workflow_execution.history())
        repair_run_id = workflow_execution.run_id
        previous_history.parse()
        # get the previous execution input if none passed
        if not input and not input_file:
            wf_input = previous_history.events[0].input
        if not tags:
            tags = workflow_execution.tag_list
    else:
        previous_history = None
        repair_run_id = None
        if not tags:
            get_tag_list = getattr(workflow_class, 'get_tag_list', None)
            if get_tag_list:
                tags = get_tag_list(workflow_class, *wf_input.get('args', ()),
                                    **wf_input.get('kwargs', {}))
            else:
                tags = getattr(workflow_class, 'tag_list', None)
            if tags == Workflow.INHERIT_TAG_LIST:
                tags = None

    task_list = create_unique_task_list(workflow_id)
    logger.info('using task list {}'.format(task_list))
    decider_proc = multiprocessing.Process(
        target=decider.command.start,
        args=(
            [workflow],
            domain,
            task_list,
        ),
        kwargs={
            'nb_processes': nb_deciders,
            'repair_with': previous_history,
            'force_activities': force_activities,
            'is_standalone': True,
            'repair_workflow_id': repair or None,
            'repair_run_id': repair_run_id,
        },
    )
    decider_proc.start()

    worker_proc = multiprocessing.Process(
        target=worker.command.start,
        args=(
            domain,
            task_list,
        ),
        kwargs={
            'nb_processes': nb_workers,
            'heartbeat': heartbeat,
        },
    )
    worker_proc.start()

    print('starting workflow {}'.format(workflow), file=sys.stderr)
    ex = start_workflow.callback(
        workflow,
        domain,
        workflow_id,
        task_list,
        execution_timeout,
        tags,
        decision_tasks_timeout,
        format.input(wf_input),
        None,
        local=False,
    )
    while True:
        time.sleep(2)
        ex = helpers.get_workflow_execution(
            domain,
            ex.workflow_id,
            ex.run_id,
        )
        if display_status:
            print('status: {}'.format(ex.status), file=sys.stderr)
        if ex.status == ex.STATUS_CLOSED:
            print('execution {} finished'.format(ex.workflow_id),
                  file=sys.stderr)
            break

    os.kill(worker_proc.pid, signal.SIGTERM)
    worker_proc.join()
    os.kill(decider_proc.pid, signal.SIGTERM)
    decider_proc.join()
Example #9
0
def standalone(context,
               workflow,
               domain,
               workflow_id,
               execution_timeout,
               tags,
               decision_tasks_timeout,
               input,
               input_file,
               nb_workers,
               nb_deciders,
               heartbeat,
               display_status,
               repair,
               force_activities,
               ):
    """
    This command spawn a decider and an activity worker to execute a workflow
    with a single main process.

    """
    disable_boto_connection_pooling()

    if force_activities and not repair:
        raise ValueError(
            "You should only use --force-activities with --repair."
        )

    workflow_class = get_workflow(workflow)
    if not workflow_id:
        workflow_id = workflow_class.name

    wf_input = {}
    if input or input_file:
        wf_input = get_or_load_input(input_file, input)

    if repair:
        repair_run_id = None
        if " " in repair:
            repair, repair_run_id = repair.split(" ", 1)
        # get the previous execution history, it will serve as "default history"
        # for activities that succeeded in the previous execution
        logger.info(
            'retrieving history of previous execution: domain={} '
            'workflow_id={} run_id={}'.format(domain, repair, repair_run_id)
        )
        workflow_execution = get_workflow_execution(domain, repair, run_id=repair_run_id)
        previous_history = History(workflow_execution.history())
        repair_run_id = workflow_execution.run_id
        previous_history.parse()
        # get the previous execution input if none passed
        if not input and not input_file:
            wf_input = previous_history.events[0].input
        if not tags:
            tags = workflow_execution.tag_list
    else:
        previous_history = None
        repair_run_id = None
        if not tags:
            get_tag_list = getattr(workflow_class, 'get_tag_list', None)
            if get_tag_list:
                tags = get_tag_list(workflow_class, *wf_input.get('args', ()), **wf_input.get('kwargs', {}))
            else:
                tags = getattr(workflow_class, 'tag_list', None)
            if tags == Workflow.INHERIT_TAG_LIST:
                tags = None

    task_list = create_unique_task_list(workflow_id)
    logger.info('using task list {}'.format(task_list))
    decider_proc = multiprocessing.Process(
        target=decider.command.start,
        args=(
            [workflow],
            domain,
            task_list,
        ),
        kwargs={
            'nb_processes': nb_deciders,
            'repair_with': previous_history,
            'force_activities': force_activities,
            'is_standalone': True,
            'repair_workflow_id': repair or None,
            'repair_run_id': repair_run_id,
        },
    )
    decider_proc.start()

    worker_proc = multiprocessing.Process(
        target=worker.command.start,
        args=(
            domain,
            task_list,
        ),
        kwargs={
            'nb_processes': nb_workers,
            'heartbeat': heartbeat,
        },
    )
    worker_proc.start()

    print('starting workflow {}'.format(workflow), file=sys.stderr)
    ex = start_workflow.callback(
        workflow,
        domain,
        workflow_id,
        task_list,
        execution_timeout,
        tags,
        decision_tasks_timeout,
        format.input(wf_input),
        None,
        local=False,
    )
    while True:
        time.sleep(2)
        ex = helpers.get_workflow_execution(
            domain,
            ex.workflow_id,
            ex.run_id,
        )
        if display_status:
            print('status: {}'.format(ex.status), file=sys.stderr)
        if ex.status == ex.STATUS_CLOSED:
            print('execution {} finished'.format(ex.workflow_id), file=sys.stderr)
            break

    os.kill(worker_proc.pid, signal.SIGTERM)
    worker_proc.join()
    os.kill(decider_proc.pid, signal.SIGTERM)
    decider_proc.join()