예제 #1
0
def previously_completed_steps(task, related_steps, **kwargs):
    """
    Assign a new task to the entry-level worker of the specified tasks.
    If no worker can be assigned, return the unmodified task.

    Args:
        task (orchestra.models.Task):
            The newly created task to assign.
        related_steps ([str]):
            List of step slugs from which to attempt to assign a worker.

    Returns:
        task (orchestra.models.Task): The modified task object.

    Raises:
        orchestra.core.errors.AssignmentPolicyError:
            Machine steps cannot be included in an assignment policy.
    """
    if related_steps is None:
        raise AssignmentPolicyError('No related steps given')

    workflow_version = task.step.workflow_version
    for step_slug in related_steps:
        step = workflow_version.steps.get(slug=step_slug)
        if not step.is_human:
            raise AssignmentPolicyError('Machine step should not be '
                                        'member of assignment policy')
    related_tasks = (Task.objects.filter(
        step__slug__in=related_steps,
        project=task.project).select_related('step'))
    for related_task in related_tasks:
        entry_level_assignment = assignment_history(related_task).first()
        if entry_level_assignment and entry_level_assignment.worker:
            try:
                return assign_task(entry_level_assignment.worker.id, task.id)
            except WorkerCertificationError:
                # Task could not be assigned to related worker, try with
                # another related worker
                logger.warning(
                    'Tried to assign worker %s to step %s, for '
                    'which they are not certified',
                    entry_level_assignment.worker.id,
                    task.step.slug,
                    exc_info=True)
            except Exception:
                logger.warning('Unable to assign task.', exc_info=True)
    return task
예제 #2
0
def _preassign_workers(task, policy_type):
    """
    Assign a new task to a worker according to its assignment policy,
    leaving the task unchanged if policy not present.

    Args:
        task (orchestra.models.Task):
            The newly created task to assign.
        policy_type (string):
            The type of assignment policy to use, from the AssignmentPolicyType

    Returns:
        task (orchestra.models.Task):
            The modified task object.

    Raises:
        orchestra.core.errors.AssignmentPolicyError:
            The specified assignment policy type is not supported or a
            machine step is given an assignment policy.
    """
    step = task.step
    policy = step.assignment_policy.get('policy_function',
                                        {}).get(policy_type, {})
    policy_path = policy.get('path', '')
    policy_kwargs = policy.get('kwargs', {})

    if not step.is_human:
        if policy:
            raise AssignmentPolicyError('Machine step should not have '
                                        'assignment policy.')
    elif not policy:
        raise AssignmentPolicyError('Assignment policy incorrectly specified.')
    else:
        try:
            policy_function = locate(policy_path)
            task = policy_function(task, **policy_kwargs)
        except Exception as e:
            raise AssignmentPolicyError(e)
    return task
예제 #3
0
def _preassign_workers(task):
    """
    Assign a new task to a worker according to its assignment policy,
    leaving the task unchanged if policy not present.

    Args:
        task (orchestra.models.Task):
            The newly created task to assign.

    Returns:
        task (orchestra.models.Task):
            The modified task object.

    Raises:
        orchestra.core.errors.AssignmentPolicyError:
            The specified assignment policy type is not supported or a
            machine step is given an assignment policy.
    """
    step = task.step
    policy = step.assignment_policy.get('policy')
    related_steps = step.assignment_policy.get('steps')

    if not step.is_human:
        if policy:
            raise AssignmentPolicyError('Machine step should not have '
                                        'assignment policy.')
    elif (policy == 'previously_completed_steps'
          and related_steps is not None):
        task = _assign_worker_from_previously_completed_steps(
            task, related_steps)
    elif policy == 'anyone_certified':
        # Leave the task in the awaiting processing pool
        pass
    else:
        raise AssignmentPolicyError('Assignment policy incorrectly specified.')
    return task