Skip to content

_sync_core_tasks

FUNCTION DESCRIPTION
sync_core_tasks

Update the set of tasks marked as core in the database, based on on-disk

Functions:

sync_core_tasks(*, resources_and_groups, base=None, add=None, remove=None)

Update the set of tasks marked as core in the database, based on on-disk configuration files.

Source code in fractal_server/cli/_sync_core_tasks.py
def sync_core_tasks(
    *,
    resources_and_groups: Path,
    base: Path | None = None,
    add: Path | None = None,
    remove: Path | None = None,
):
    """
    Update the set of tasks marked as core in the database, based on on-disk
    configuration files.
    """

    import json
    import sys

    from sqlalchemy import select
    from sqlalchemy import update

    from fractal_server.app.db import get_sync_db
    from fractal_server.app.models import Resource
    from fractal_server.app.models import TaskGroupV2
    from fractal_server.app.models import TaskV2
    from fractal_server.app.models import UserGroup
    from fractal_server.config import get_email_settings
    from fractal_server.send_mail import send_fractal_email_or_log_failure
    from fractal_server.syringe import Inject

    from ._aux_sync_core_tasks import _count_core_tasks
    from ._aux_sync_core_tasks import _get_final_set

    resources_and_groups: list[dict[str, int]] = json.loads(
        resources_and_groups.read_text()
    )
    final_set = _get_final_set(
        base=base,
        add=add,
        remove=remove,
    )
    with next(get_sync_db()) as db:
        count_pre = _count_core_tasks(db)
        print(f"Initial count of core tasks: {count_pre}")

        try:
            # Mark all tasks as not core
            stm = (
                update(TaskV2)
                .where(TaskV2.is_core.is_(True))
                .values(is_core=False)
            )
            db.execute(stm)

            for obj in resources_and_groups:
                resource_id = obj["resource_id"]
                user_group_id = obj["user_group_id"]
                db.get_one(Resource, resource_id)
                db.get_one(UserGroup, user_group_id)
                for pkg_name, version, task_name in final_set:
                    stm = (
                        select(TaskV2)
                        .join(
                            TaskGroupV2, TaskV2.taskgroupv2_id == TaskGroupV2.id
                        )
                        .where(TaskGroupV2.user_group_id == user_group_id)
                        .where(TaskGroupV2.resource_id == resource_id)
                        .where(TaskGroupV2.pkg_name == pkg_name)
                        .where(TaskGroupV2.version == version)
                        .where(TaskV2.name == task_name)
                    )
                    res = db.execute(stm)
                    task = res.scalar_one_or_none()
                    if task is not None:
                        task.is_core = True
                        db.add(task)
                        db.flush()
            db.commit()
        except Exception as exc:
            db.rollback()
            msg = (
                "An exception took place, exit without updating the database."
                f" Original error: {str(exc)}"
            )
            email_settings = Inject(get_email_settings)
            send_fractal_email_or_log_failure(
                subject="Failed core-tasks synchronization",
                msg=msg,
                email_settings=email_settings.public,
            )
            sys.exit(msg)
        finally:
            count_post = _count_core_tasks(db)
            print(f"Final count of core tasks: {count_post}")