Skip to content

Task

FUNCTION DESCRIPTION
create_task

Create a new task

delete_task

Delete a task

get_task

Get info on a specific task

get_task_list

Get list of available tasks

patch_task

Edit a specific task (restricted to task owner)

Classes

Functions:

create_task(task, user_group_id=None, private=False, user=Depends(get_api_user), db=Depends(get_async_db)) async

Create a new task

Source code in fractal_server/app/routes/api/v2/task.py
@router.post("/", response_model=TaskRead, status_code=status.HTTP_201_CREATED)
async def create_task(
    task: TaskCreate,
    user_group_id: int | None = None,
    private: bool = False,
    user: UserOAuth = Depends(get_api_user),
    db: AsyncSession = Depends(get_async_db),
) -> TaskV2:
    """
    Create a new task
    """

    # Get validated resource and profile
    resource, profile = await validate_user_profile(
        user=user,
        db=db,
    )
    resource_id = resource.id

    # Validate query parameters related to user-group ownership
    user_group_id = await _get_valid_user_group_id(
        user_group_id=user_group_id,
        private=private,
        user_id=user.id,
        db=db,
    )

    if task.type == TaskType.PARALLEL and (
        task.args_schema_non_parallel is not None
        or task.meta_non_parallel is not None
    ):
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail=(
                "Cannot set `TaskV2.args_schema_non_parallel` or "
                "`TaskV2.args_schema_non_parallel` if TaskV2 is parallel"
            ),
        )
    elif task.type == TaskType.NON_PARALLEL and (
        task.args_schema_parallel is not None or task.meta_parallel is not None
    ):
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail=(
                "Cannot set `TaskV2.args_schema_parallel` or "
                "`TaskV2.args_schema_parallel` if TaskV2 is non_parallel"
            ),
        )

    # Add task

    db_task = TaskV2(**task.model_dump(exclude_unset=True))
    pkg_name = db_task.name
    await _verify_non_duplication_user_constraint(
        db=db,
        pkg_name=pkg_name,
        user_id=user.id,
        version=db_task.version,
        user_resource_id=resource_id,
    )
    await _verify_non_duplication_group_constraint(
        db=db,
        pkg_name=pkg_name,
        user_group_id=user_group_id,
        version=db_task.version,
    )
    db_task_group = TaskGroupV2(
        user_id=user.id,
        user_group_id=user_group_id,
        resource_id=resource_id,
        active=True,
        task_list=[db_task],
        origin=TaskGroupOriginEnum.OTHER,
        version=db_task.version,
        pkg_name=pkg_name,
        pinned_package_versions_pre={},
        pinned_package_versions_post={},
    )
    db.add(db_task_group)
    async with integrity_error_to_422(db):
        await db.commit()
    await db.refresh(db_task)

    return db_task

delete_task(task_id, user=Depends(get_api_user), db=Depends(get_async_db)) async

Delete a task

Source code in fractal_server/app/routes/api/v2/task.py
@router.delete("/{task_id}/", status_code=204)
async def delete_task(
    task_id: int,
    user: UserOAuth = Depends(get_api_user),
    db: AsyncSession = Depends(get_async_db),
) -> Response:
    """
    Delete a task
    """
    raise HTTPException(
        status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
        detail=(
            "Cannot delete single tasks, "
            "please operate directly on task groups."
        ),
    )

get_task(task_id, user=Depends(get_api_guest), db=Depends(get_async_db)) async

Get info on a specific task

Source code in fractal_server/app/routes/api/v2/task.py
@router.get("/{task_id}/", response_model=TaskRead)
async def get_task(
    task_id: int,
    user: UserOAuth = Depends(get_api_guest),
    db: AsyncSession = Depends(get_async_db),
) -> TaskV2:
    """
    Get info on a specific task
    """
    task = await _get_task_read_access(task_id=task_id, user_id=user.id, db=db)
    return task

get_task_list(user=Depends(get_api_guest), db=Depends(get_async_db)) async

Get list of available tasks

Source code in fractal_server/app/routes/api/v2/task.py
@router.get("/", response_model=list[TaskReadSlim])
async def get_task_list(
    user: UserOAuth = Depends(get_api_guest),
    db: AsyncSession = Depends(get_async_db),
) -> list[dict[str, Any]]:
    """
    Get list of available tasks
    """

    user_resource_id = await _get_user_resource_id(user_id=user.id, db=db)

    stm = (
        select(TaskV2)
        .join(TaskGroupV2, TaskGroupV2.id == TaskV2.taskgroupv2_id)
        .where(TaskGroupV2.resource_id == user_resource_id)
        .where(
            or_(
                TaskGroupV2.user_id == user.id,
                TaskGroupV2.user_group_id.in_(
                    select(LinkUserGroup.group_id).where(
                        LinkUserGroup.user_id == user.id
                    )
                ),
            )
        )
        .order_by(TaskV2.id)
    )

    res = await db.execute(stm)
    task_list = list(res.scalars().all())

    return task_list

patch_task(task_id, task_update, user=Depends(get_api_user), db=Depends(get_async_db)) async

Edit a specific task (restricted to task owner)

Source code in fractal_server/app/routes/api/v2/task.py
@router.patch("/{task_id}/", response_model=TaskRead)
async def patch_task(
    task_id: int,
    task_update: TaskUpdate,
    user: UserOAuth = Depends(get_api_user),
    db: AsyncSession = Depends(get_async_db),
) -> TaskV2:
    """
    Edit a specific task (restricted to task owner)
    """

    # Retrieve task from database
    db_task = await _get_task_full_access(
        task_id=task_id, user_id=user.id, db=db
    )
    update = task_update.model_dump(exclude_unset=True)

    task_group = await db.get_one(TaskGroupV2, db_task.taskgroupv2_id)
    if task_group.origin != TaskGroupOriginEnum.OTHER:
        for argname in (
            "command_parallel",
            "command_non_parallel",
            "input_types",
            "output_types",
        ):
            if argname in update:
                raise HTTPException(
                    status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
                    detail=(
                        f"Cannot update '{argname}' when {task_group.origin=}."
                    ),
                )

    # Forbid changes that set a previously unset command
    if db_task.type == TaskType.NON_PARALLEL and "command_parallel" in update:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail="Cannot set an unset `command_parallel`.",
        )
    if db_task.type == TaskType.PARALLEL and "command_non_parallel" in update:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail="Cannot set an unset `command_non_parallel`.",
        )

    for key, value in update.items():
        setattr(db_task, key, value)

    await db.commit()
    await db.refresh(db_task)
    return db_task