fractal-server 2.14.0a18__tar.gz → 2.14.0a20__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/PKG-INFO +1 -1
- fractal_server-2.14.0a20/fractal_server/__init__.py +1 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_collection_custom.py +4 -9
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/base_runner.py +19 -18
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/local/runner.py +2 -8
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +45 -17
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/remote.py +21 -35
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_ssh/runner.py +22 -19
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_sudo/runner.py +6 -2
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/task_files.py +16 -6
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/collect.py +2 -2
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/collect.py +2 -2
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_database.py +29 -1
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/pyproject.toml +2 -2
- fractal_server-2.14.0a18/fractal_server/__init__.py +0 -1
- fractal_server-2.14.0a18/fractal_server/app/runner/executors/slurm_common/_handle_exception_proxy.py +0 -17
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/LICENSE +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/README.md +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/__main__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/history/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/security.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/user_settings.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/accounting.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/history.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/task_group.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/job.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/project.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/task.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/dataset.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/history.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/images.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/submit.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_group.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/verify_image_types.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/workflow.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/current_user.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/group.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/router.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/users.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/pagination.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/components.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/compress_folder.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/exceptions.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/local/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/utils_executors.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/extract_archive.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/filenames.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/run_subprocess.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/shutdown.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/_local.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/_slurm_ssh.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/_slurm_sudo.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/db_tools.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/runner.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/task_interface.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/versions.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/_filter_validators.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/_validators.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/user.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/user_group.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/user_settings.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/accounting.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/dumps.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/history.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/manifest.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/task.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/task_group.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/security/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/security/signup_email.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/user_settings.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/config.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/images/models.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/logger.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/main.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/py.typed +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/syringe.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/_utils.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/deactivate.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/reactivate.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_background.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_package_names.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_templates.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/urls.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/utils.py +0 -0
- {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/zip_tools.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "2.14.0a20"
|
@@ -12,9 +12,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|
12
12
|
from ._aux_functions_tasks import _get_valid_user_group_id
|
13
13
|
from ._aux_functions_tasks import _verify_non_duplication_group_constraint
|
14
14
|
from ._aux_functions_tasks import _verify_non_duplication_user_constraint
|
15
|
-
from fractal_server.app.db import DBSyncSession
|
16
15
|
from fractal_server.app.db import get_async_db
|
17
|
-
from fractal_server.app.db import get_sync_db
|
18
16
|
from fractal_server.app.models import UserOAuth
|
19
17
|
from fractal_server.app.models.v2 import TaskGroupV2
|
20
18
|
from fractal_server.app.routes.auth import current_active_verified_user
|
@@ -31,7 +29,7 @@ from fractal_server.tasks.v2.utils_background import (
|
|
31
29
|
_prepare_tasks_metadata,
|
32
30
|
)
|
33
31
|
from fractal_server.tasks.v2.utils_database import (
|
34
|
-
|
32
|
+
create_db_tasks_and_update_task_group_async,
|
35
33
|
)
|
36
34
|
|
37
35
|
router = APIRouter()
|
@@ -47,10 +45,7 @@ async def collect_task_custom(
|
|
47
45
|
private: bool = False,
|
48
46
|
user_group_id: Optional[int] = None,
|
49
47
|
user: UserOAuth = Depends(current_active_verified_user),
|
50
|
-
db: AsyncSession = Depends(get_async_db),
|
51
|
-
db_sync: DBSyncSession = Depends(
|
52
|
-
get_sync_db
|
53
|
-
), # FIXME: using both sync/async
|
48
|
+
db: AsyncSession = Depends(get_async_db),
|
54
49
|
) -> list[TaskReadV2]:
|
55
50
|
|
56
51
|
settings = Inject(get_settings)
|
@@ -168,10 +163,10 @@ async def collect_task_custom(
|
|
168
163
|
await db.refresh(task_group)
|
169
164
|
db.expunge(task_group)
|
170
165
|
|
171
|
-
task_group =
|
166
|
+
task_group = await create_db_tasks_and_update_task_group_async(
|
172
167
|
task_list=task_list,
|
173
168
|
task_group_id=task_group.id,
|
174
|
-
db=
|
169
|
+
db=db,
|
175
170
|
)
|
176
171
|
|
177
172
|
logger.debug(
|
@@ -25,30 +25,25 @@ class BaseRunner(object):
|
|
25
25
|
Base class for Fractal runners.
|
26
26
|
"""
|
27
27
|
|
28
|
-
def shutdown(self, *args, **kwargs):
|
29
|
-
raise NotImplementedError()
|
30
|
-
|
31
28
|
def submit(
|
32
29
|
self,
|
33
30
|
func: callable,
|
34
31
|
parameters: dict[str, Any],
|
35
32
|
history_unit_id: int,
|
36
|
-
task_files: TaskFiles,
|
37
33
|
task_type: TaskTypeType,
|
34
|
+
task_files: TaskFiles,
|
38
35
|
config: Any,
|
39
36
|
) -> tuple[Any, BaseException]:
|
40
37
|
"""
|
41
38
|
Run a single fractal task.
|
42
39
|
|
43
|
-
# FIXME: Describe more in detail
|
44
|
-
|
45
40
|
Args:
|
46
41
|
func: Function to be executed.
|
47
|
-
parameters:
|
48
|
-
|
49
|
-
|
50
|
-
Database ID of the corresponding `HistoryItemV2` entry.
|
42
|
+
parameters: Dictionary of parameters.
|
43
|
+
history_unit_id:
|
44
|
+
Database ID of the corresponding `HistoryUnit` entry.
|
51
45
|
task_type: Task type.
|
46
|
+
task_files: `TaskFiles` object.
|
52
47
|
config: Runner-specific parameters.
|
53
48
|
"""
|
54
49
|
raise NotImplementedError()
|
@@ -65,16 +60,14 @@ class BaseRunner(object):
|
|
65
60
|
"""
|
66
61
|
Run a parallel fractal task.
|
67
62
|
|
68
|
-
# FIXME: Describe more in detail
|
69
|
-
|
70
63
|
Args:
|
71
64
|
func: Function to be executed.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
Database ID of the corresponding `HistoryItemV2` entry.
|
65
|
+
parameters:
|
66
|
+
Dictionary of parameters. Must include `zarr_urls` key.
|
67
|
+
history_unit_ids:
|
68
|
+
Database IDs of the corresponding `HistoryUnit` entries.
|
77
69
|
task_type: Task type.
|
70
|
+
task_files: `TaskFiles` object.
|
78
71
|
config: Runner-specific parameters.
|
79
72
|
"""
|
80
73
|
raise NotImplementedError()
|
@@ -115,7 +108,7 @@ class BaseRunner(object):
|
|
115
108
|
list_task_files: list[TaskFiles],
|
116
109
|
) -> None:
|
117
110
|
"""
|
118
|
-
Validate parameters for `
|
111
|
+
Validate parameters for `multisubmit` method
|
119
112
|
|
120
113
|
Args:
|
121
114
|
list_parameters: List of parameters dictionaries.
|
@@ -152,6 +145,14 @@ class BaseRunner(object):
|
|
152
145
|
task_type: TaskTypeType,
|
153
146
|
list_parameters: list[dict[str, Any]],
|
154
147
|
) -> None:
|
148
|
+
"""
|
149
|
+
Run preliminary check for multisubmit inputs.
|
150
|
+
|
151
|
+
Args:
|
152
|
+
history_unit_ids:
|
153
|
+
task_type:
|
154
|
+
list_parameters:
|
155
|
+
"""
|
155
156
|
if task_type in ["compound", "converter_compound"]:
|
156
157
|
if len(history_unit_ids) != 1:
|
157
158
|
raise NotImplementedError(
|
@@ -40,16 +40,12 @@ class LocalRunner(BaseRunner):
|
|
40
40
|
logger.debug("Enter LocalRunner")
|
41
41
|
return self
|
42
42
|
|
43
|
-
def
|
44
|
-
logger.debug("
|
43
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
44
|
+
logger.debug("Exit LocalRunner")
|
45
45
|
self.executor.shutdown(
|
46
46
|
wait=False,
|
47
47
|
cancel_futures=True,
|
48
48
|
)
|
49
|
-
|
50
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
51
|
-
logger.debug("Exit LocalRunner")
|
52
|
-
self.shutdown()
|
53
49
|
return self.executor.__exit__(exc_type, exc_val, exc_tb)
|
54
50
|
|
55
51
|
def submit(
|
@@ -193,8 +189,6 @@ class LocalRunner(BaseRunner):
|
|
193
189
|
pass
|
194
190
|
|
195
191
|
while active_futures:
|
196
|
-
# FIXME: add shutdown detection
|
197
|
-
# if file exists: cancel all futures, and raise
|
198
192
|
finished_futures = [
|
199
193
|
index_and_future
|
200
194
|
for index_and_future in active_futures.items()
|
@@ -13,11 +13,11 @@ from ..slurm_common._slurm_config import SlurmConfig
|
|
13
13
|
from ..slurm_common.slurm_job_task_models import SlurmJob
|
14
14
|
from ..slurm_common.slurm_job_task_models import SlurmTask
|
15
15
|
from ._batching import heuristics
|
16
|
-
from ._handle_exception_proxy import _handle_exception_proxy
|
17
16
|
from ._job_states import STATES_FINISHED
|
18
17
|
from fractal_server import __VERSION__
|
19
18
|
from fractal_server.app.db import get_sync_db
|
20
19
|
from fractal_server.app.runner.exceptions import JobExecutionError
|
20
|
+
from fractal_server.app.runner.exceptions import TaskExecutionError
|
21
21
|
from fractal_server.app.runner.executors.base_runner import BaseRunner
|
22
22
|
from fractal_server.app.runner.filenames import SHUTDOWN_FILENAME
|
23
23
|
from fractal_server.app.runner.task_files import MULTISUBMIT_PREFIX
|
@@ -96,8 +96,12 @@ class BaseSlurmRunner(BaseRunner):
|
|
96
96
|
raise NotImplementedError("Implement in child class.")
|
97
97
|
|
98
98
|
def run_squeue(self, job_ids: list[str]) -> tuple[bool, str]:
|
99
|
+
|
99
100
|
# FIXME: review different cases (exception vs no job found)
|
100
|
-
|
101
|
+
|
102
|
+
if len(job_ids) == 0:
|
103
|
+
return (False, "")
|
104
|
+
|
101
105
|
job_id_single_str = ",".join([str(j) for j in job_ids])
|
102
106
|
cmd = (
|
103
107
|
f"squeue --noheader --format='%i %T' --jobs {job_id_single_str}"
|
@@ -109,10 +113,10 @@ class BaseSlurmRunner(BaseRunner):
|
|
109
113
|
stdout = self._run_local_cmd(cmd)
|
110
114
|
else:
|
111
115
|
stdout = self._run_remote_cmd(cmd)
|
112
|
-
return True, stdout
|
116
|
+
return (True, stdout)
|
113
117
|
except Exception as e:
|
114
118
|
logger.info(f"{cmd=} failed with {str(e)}")
|
115
|
-
return False, ""
|
119
|
+
return (False, "")
|
116
120
|
|
117
121
|
def _get_finished_jobs(self, job_ids: list[str]) -> set[str]:
|
118
122
|
# If there is no Slurm job to check, return right away
|
@@ -353,11 +357,31 @@ class BaseSlurmRunner(BaseRunner):
|
|
353
357
|
outdata = f.read()
|
354
358
|
success, output = cloudpickle.loads(outdata)
|
355
359
|
if success:
|
360
|
+
# Task succeeded
|
356
361
|
result = output
|
357
|
-
return result, None
|
362
|
+
return (result, None)
|
358
363
|
else:
|
359
|
-
|
360
|
-
|
364
|
+
# Task failed in a controlled way, and produced an `output`
|
365
|
+
# object which is a dictionary with required keys
|
366
|
+
# `exc_type_name` and `traceback_string` and with optional
|
367
|
+
# keys `workflow_task_order`, `workflow_task_id` and
|
368
|
+
# `task_name`.
|
369
|
+
exc_type_name = output.get("exc_type_name")
|
370
|
+
logger.debug(
|
371
|
+
f"Output pickle contains a '{exc_type_name}' exception."
|
372
|
+
)
|
373
|
+
traceback_string = output.get("traceback_string")
|
374
|
+
kwargs = {
|
375
|
+
key: output[key]
|
376
|
+
for key in [
|
377
|
+
"workflow_task_order",
|
378
|
+
"workflow_task_id",
|
379
|
+
"task_name",
|
380
|
+
]
|
381
|
+
if key in output.keys()
|
382
|
+
}
|
383
|
+
exception = TaskExecutionError(traceback_string, **kwargs)
|
384
|
+
return (None, exception)
|
361
385
|
|
362
386
|
except Exception as e:
|
363
387
|
exception = JobExecutionError(f"ERROR, {str(e)}")
|
@@ -369,8 +393,7 @@ class BaseSlurmRunner(BaseRunner):
|
|
369
393
|
f"for {task.index=}."
|
370
394
|
)
|
371
395
|
exception = SHUTDOWN_EXCEPTION
|
372
|
-
|
373
|
-
return None, exception
|
396
|
+
return (None, exception)
|
374
397
|
finally:
|
375
398
|
Path(task.input_pickle_file_local).unlink(missing_ok=True)
|
376
399
|
Path(task.output_pickle_file_local).unlink(missing_ok=True)
|
@@ -460,10 +483,10 @@ class BaseSlurmRunner(BaseRunner):
|
|
460
483
|
)
|
461
484
|
logger.info(f"[submit] END submission phase, {self.job_ids=}")
|
462
485
|
|
463
|
-
# FIXME: replace this sleep a more precise check
|
486
|
+
# FIXME: replace this sleep with a more precise check
|
464
487
|
settings = Inject(get_settings)
|
465
488
|
sleep_time = settings.FRACTAL_SLURM_INTERVAL_BEFORE_RETRIEVAL
|
466
|
-
logger.warning(f"[submit] Now sleep {sleep_time}
|
489
|
+
logger.warning(f"[submit] Now sleep {sleep_time} seconds.")
|
467
490
|
time.sleep(sleep_time)
|
468
491
|
|
469
492
|
# Retrieval phase
|
@@ -485,7 +508,9 @@ class BaseSlurmRunner(BaseRunner):
|
|
485
508
|
for slurm_job_id in finished_job_ids:
|
486
509
|
logger.debug(f"[submit] Now process {slurm_job_id=}")
|
487
510
|
slurm_job = self.jobs.pop(slurm_job_id)
|
488
|
-
self._copy_files_from_remote_to_local(
|
511
|
+
self._copy_files_from_remote_to_local(
|
512
|
+
slurm_job
|
513
|
+
) # FIXME: add prefix # noqa
|
489
514
|
was_job_scancelled = slurm_job_id in scancelled_job_ids
|
490
515
|
result, exception = self._postprocess_single_task(
|
491
516
|
task=slurm_job.tasks[0],
|
@@ -506,7 +531,8 @@ class BaseSlurmRunner(BaseRunner):
|
|
506
531
|
db_sync=db,
|
507
532
|
)
|
508
533
|
|
509
|
-
|
534
|
+
if len(self.jobs) > 0:
|
535
|
+
time.sleep(self.poll_interval)
|
510
536
|
|
511
537
|
logger.info("[submit] END")
|
512
538
|
return result, exception
|
@@ -650,10 +676,10 @@ class BaseSlurmRunner(BaseRunner):
|
|
650
676
|
|
651
677
|
logger.info(f"END submission phase, {self.job_ids=}")
|
652
678
|
|
653
|
-
# FIXME: replace this sleep a more precise check
|
679
|
+
# FIXME: replace this sleep with a more precise check
|
654
680
|
settings = Inject(get_settings)
|
655
681
|
sleep_time = settings.FRACTAL_SLURM_INTERVAL_BEFORE_RETRIEVAL
|
656
|
-
logger.warning(f"[submit] Now sleep {sleep_time}
|
682
|
+
logger.warning(f"[submit] Now sleep {sleep_time} seconds.")
|
657
683
|
time.sleep(sleep_time)
|
658
684
|
|
659
685
|
# FIXME: Could we merge the submit/multisubmit retrieval phases?
|
@@ -677,7 +703,9 @@ class BaseSlurmRunner(BaseRunner):
|
|
677
703
|
for slurm_job_id in finished_job_ids:
|
678
704
|
logger.info(f"[multisubmit] Now process {slurm_job_id=}")
|
679
705
|
slurm_job = self.jobs.pop(slurm_job_id)
|
680
|
-
self._copy_files_from_remote_to_local(
|
706
|
+
self._copy_files_from_remote_to_local(
|
707
|
+
slurm_job
|
708
|
+
) # FIXME: add prefix # noqa
|
681
709
|
for task in slurm_job.tasks:
|
682
710
|
logger.info(f"[multisubmit] Now process {task.index=}")
|
683
711
|
was_job_scancelled = slurm_job_id in scancelled_job_ids
|
@@ -713,7 +741,7 @@ class BaseSlurmRunner(BaseRunner):
|
|
713
741
|
time.sleep(self.poll_interval)
|
714
742
|
return results, exceptions
|
715
743
|
|
716
|
-
def check_fractal_server_versions(self):
|
744
|
+
def check_fractal_server_versions(self) -> None:
|
717
745
|
"""
|
718
746
|
Compare fractal-server versions of local/remote Python interpreters.
|
719
747
|
"""
|
@@ -19,7 +19,6 @@ import os
|
|
19
19
|
import sys
|
20
20
|
from typing import Literal
|
21
21
|
from typing import Optional
|
22
|
-
from typing import Type
|
23
22
|
from typing import Union
|
24
23
|
|
25
24
|
import cloudpickle
|
@@ -27,30 +26,6 @@ import cloudpickle
|
|
27
26
|
from fractal_server import __VERSION__
|
28
27
|
|
29
28
|
|
30
|
-
class ExceptionProxy:
|
31
|
-
"""
|
32
|
-
Proxy class to serialise exceptions
|
33
|
-
|
34
|
-
In general exceptions are not serialisable. This proxy class saves the
|
35
|
-
serialisable content of an exception. On the receiving end, it can be used
|
36
|
-
to reconstruct a TaskExecutionError.
|
37
|
-
|
38
|
-
Attributes:
|
39
|
-
exc_type_name: Name of the exception type
|
40
|
-
tb: TBD
|
41
|
-
args: TBD
|
42
|
-
kwargs: TBD
|
43
|
-
"""
|
44
|
-
|
45
|
-
def __init__(
|
46
|
-
self, exc_type: Type[BaseException], tb: str, *args, **kwargs
|
47
|
-
):
|
48
|
-
self.exc_type_name: str = exc_type.__name__
|
49
|
-
self.tb: str = tb
|
50
|
-
self.args = args
|
51
|
-
self.kwargs: dict = kwargs
|
52
|
-
|
53
|
-
|
54
29
|
class FractalVersionMismatch(RuntimeError):
|
55
30
|
"""
|
56
31
|
Custom exception for version mismatch
|
@@ -141,21 +116,32 @@ def worker(
|
|
141
116
|
server_versions, fun, args, kwargs = cloudpickle.loads(indata)
|
142
117
|
_check_versions_mismatch(server_versions)
|
143
118
|
|
144
|
-
result = True, fun(*args, **kwargs)
|
119
|
+
result = (True, fun(*args, **kwargs))
|
145
120
|
out = cloudpickle.dumps(result)
|
146
121
|
except Exception as e:
|
122
|
+
# Exception objects are not serialisable. Here we save the relevant
|
123
|
+
# exception contents in a serializable dictionary. Note that whenever
|
124
|
+
# the task failed "properly", the exception is a `TaskExecutionError`
|
125
|
+
# and it has additional attributes.
|
126
|
+
|
147
127
|
import traceback
|
148
128
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
**e.__dict__,
|
129
|
+
exc_type, exc_value, traceback_obj = sys.exc_info()
|
130
|
+
traceback_obj = traceback_obj.tb_next
|
131
|
+
traceback_list = traceback.format_exception(
|
132
|
+
exc_type,
|
133
|
+
exc_value,
|
134
|
+
traceback_obj,
|
156
135
|
)
|
157
|
-
|
158
|
-
|
136
|
+
traceback_string = "".join(traceback_list)
|
137
|
+
exc_proxy = dict(
|
138
|
+
exc_type_name=exc_type.__name__,
|
139
|
+
traceback_string=traceback_string,
|
140
|
+
workflow_task_order=getattr(e, "workflow_task_order", None),
|
141
|
+
workflow_task_id=getattr(e, "workflow_task_id", None),
|
142
|
+
task_name=getattr(e, "task_name", None),
|
143
|
+
)
|
144
|
+
result = (False, exc_proxy)
|
159
145
|
out = cloudpickle.dumps(result)
|
160
146
|
|
161
147
|
# Write the output pickle file
|
@@ -13,7 +13,6 @@ from fractal_server.syringe import Inject
|
|
13
13
|
|
14
14
|
|
15
15
|
logger = set_logger(__name__)
|
16
|
-
# FIXME: Transform several logger.info into logger.debug.
|
17
16
|
|
18
17
|
|
19
18
|
class SlurmSSHRunner(BaseSlurmRunner):
|
@@ -72,15 +71,15 @@ class SlurmSSHRunner(BaseSlurmRunner):
|
|
72
71
|
Transfer the jobs subfolder to the remote host.
|
73
72
|
"""
|
74
73
|
|
75
|
-
# Create
|
74
|
+
# Create local archive
|
76
75
|
tarfile_path_local = compress_folder(job.workdir_local)
|
77
|
-
|
78
76
|
tarfile_name = Path(tarfile_path_local).name
|
79
77
|
logger.info(f"Subfolder archive created at {tarfile_path_local}")
|
78
|
+
|
79
|
+
# Transfer archive
|
80
80
|
tarfile_path_remote = (
|
81
81
|
job.workdir_remote.parent / tarfile_name
|
82
82
|
).as_posix()
|
83
|
-
# Transfer archive
|
84
83
|
t_0_put = time.perf_counter()
|
85
84
|
self.fractal_ssh.send_file(
|
86
85
|
local=tarfile_path_local,
|
@@ -91,7 +90,12 @@ class SlurmSSHRunner(BaseSlurmRunner):
|
|
91
90
|
f"Subfolder archive transferred to {tarfile_path_remote}"
|
92
91
|
f" - elapsed: {t_1_put - t_0_put:.3f} s"
|
93
92
|
)
|
94
|
-
|
93
|
+
|
94
|
+
# Remove local archive
|
95
|
+
Path(tarfile_path_local).unlink()
|
96
|
+
logger.debug(f"Local archive {tarfile_path_local} removed")
|
97
|
+
|
98
|
+
# Uncompress remote archive
|
95
99
|
tar_command = (
|
96
100
|
f"{self.python_worker_interpreter} -m "
|
97
101
|
"fractal_server.app.runner.extract_archive "
|
@@ -99,14 +103,6 @@ class SlurmSSHRunner(BaseSlurmRunner):
|
|
99
103
|
)
|
100
104
|
self.fractal_ssh.run_command(cmd=tar_command)
|
101
105
|
|
102
|
-
# Remove local version
|
103
|
-
t_0_rm = time.perf_counter()
|
104
|
-
Path(tarfile_path_local).unlink()
|
105
|
-
t_1_rm = time.perf_counter()
|
106
|
-
logger.info(
|
107
|
-
f"Local archive removed - elapsed: {t_1_rm - t_0_rm:.3f} s"
|
108
|
-
)
|
109
|
-
|
110
106
|
def _get_subfolder_sftp(self, job: SlurmJob) -> None:
|
111
107
|
"""
|
112
108
|
Fetch a remote folder via tar+sftp+tar
|
@@ -125,21 +121,30 @@ class SlurmSSHRunner(BaseSlurmRunner):
|
|
125
121
|
try:
|
126
122
|
rm_command = f"rm {tarfile_path_remote}"
|
127
123
|
self.fractal_ssh.run_command(cmd=rm_command)
|
124
|
+
logger.info(f"Removed {tarfile_path_remote=}")
|
128
125
|
except RuntimeError as e:
|
129
|
-
logger.
|
126
|
+
logger.info(
|
127
|
+
f"Could not remove {tarfile_path_remote=}.\n"
|
128
|
+
f"Original error: {str(e)}"
|
129
|
+
)
|
130
130
|
|
131
131
|
# Create remote tarfile
|
132
132
|
# FIXME: introduce filtering by prefix, so that when the subfolder
|
133
133
|
# includes N SLURM jobs we don't always copy the cumulative folder
|
134
134
|
# but only the relevant part
|
135
|
+
t_0_tar = time.perf_counter()
|
135
136
|
tar_command = (
|
136
137
|
f"{self.python_worker_interpreter} "
|
137
138
|
"-m fractal_server.app.runner.compress_folder "
|
138
139
|
f"{job.workdir_remote.as_posix()} "
|
139
140
|
"--remote-to-local"
|
140
141
|
)
|
141
|
-
|
142
|
-
|
142
|
+
self.fractal_ssh.run_command(cmd=tar_command)
|
143
|
+
t_1_tar = time.perf_counter()
|
144
|
+
logger.info(
|
145
|
+
f"Remote archive {tarfile_path_remote} created"
|
146
|
+
f" - elapsed: {t_1_tar - t_0_tar:.3f} s"
|
147
|
+
)
|
143
148
|
|
144
149
|
# Fetch tarfile
|
145
150
|
t_0_get = time.perf_counter()
|
@@ -157,9 +162,7 @@ class SlurmSSHRunner(BaseSlurmRunner):
|
|
157
162
|
extract_archive(Path(tarfile_path_local))
|
158
163
|
|
159
164
|
# Remove local tarfile
|
160
|
-
|
161
|
-
logger.warning(f"Remove existing file {tarfile_path_local}.")
|
162
|
-
Path(tarfile_path_local).unlink()
|
165
|
+
Path(tarfile_path_local).unlink(missing_ok=True)
|
163
166
|
|
164
167
|
t_1 = time.perf_counter()
|
165
168
|
logger.info(f"[_get_subfolder_sftp] End - elapsed: {t_1 - t_0:.3f} s")
|
@@ -17,7 +17,6 @@ from fractal_server.syringe import Inject
|
|
17
17
|
|
18
18
|
|
19
19
|
logger = set_logger(__name__)
|
20
|
-
# FIXME: Transform several logger.info into logger.debug.
|
21
20
|
|
22
21
|
|
23
22
|
def _subprocess_run_or_raise(
|
@@ -93,7 +92,9 @@ class SudoSlurmRunner(BaseSlurmRunner):
|
|
93
92
|
"""
|
94
93
|
Note: this would differ for SSH
|
95
94
|
"""
|
96
|
-
logger.
|
95
|
+
logger.debug(
|
96
|
+
f"[_copy_files_from_remote_to_local] {job.slurm_job_id=} START"
|
97
|
+
)
|
97
98
|
source_target_list = [
|
98
99
|
(job.slurm_stdout_remote, job.slurm_stdout_local),
|
99
100
|
(job.slurm_stderr_remote, job.slurm_stderr_local),
|
@@ -139,6 +140,9 @@ class SudoSlurmRunner(BaseSlurmRunner):
|
|
139
140
|
f"SKIP copy {source} into {target}. "
|
140
141
|
f"Original error: {str(e)}"
|
141
142
|
)
|
143
|
+
logger.debug(
|
144
|
+
f"[_copy_files_from_remote_to_local] {job.slurm_job_id=} END"
|
145
|
+
)
|
142
146
|
|
143
147
|
def _run_remote_cmd(self, cmd: str) -> str:
|
144
148
|
res = _run_command_as_user(
|
{fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/task_files.py
RENAMED
@@ -6,8 +6,14 @@ from pydantic import BaseModel
|
|
6
6
|
|
7
7
|
from fractal_server.string_tools import sanitize_string
|
8
8
|
|
9
|
+
SUBMIT_PREFIX = "non_par"
|
10
|
+
MULTISUBMIT_PREFIX = "par"
|
11
|
+
|
9
12
|
|
10
|
-
def task_subfolder_name(
|
13
|
+
def task_subfolder_name(
|
14
|
+
order: Union[int, str],
|
15
|
+
task_name: str,
|
16
|
+
) -> str:
|
11
17
|
"""
|
12
18
|
Get name of task-specific subfolder.
|
13
19
|
|
@@ -21,7 +27,15 @@ def task_subfolder_name(order: Union[int, str], task_name: str) -> str:
|
|
21
27
|
|
22
28
|
class TaskFiles(BaseModel):
|
23
29
|
"""
|
24
|
-
|
30
|
+
Files related to a task.
|
31
|
+
|
32
|
+
Attributes:
|
33
|
+
root_dir_local:
|
34
|
+
root_dir_remote:
|
35
|
+
task_name:
|
36
|
+
task_order:
|
37
|
+
component:
|
38
|
+
prefix:
|
25
39
|
"""
|
26
40
|
|
27
41
|
# Parent directory
|
@@ -114,7 +128,3 @@ class TaskFiles(BaseModel):
|
|
114
128
|
metadiff_file_remote=self.metadiff_file_remote,
|
115
129
|
log_file_remote=self.log_file_remote,
|
116
130
|
)
|
117
|
-
|
118
|
-
|
119
|
-
SUBMIT_PREFIX = "non_par"
|
120
|
-
MULTISUBMIT_PREFIX = "par"
|
{fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/collect.py
RENAMED
@@ -6,7 +6,7 @@ from pathlib import Path
|
|
6
6
|
from tempfile import TemporaryDirectory
|
7
7
|
from typing import Optional
|
8
8
|
|
9
|
-
from ..utils_database import
|
9
|
+
from ..utils_database import create_db_tasks_and_update_task_group_sync
|
10
10
|
from ._utils import _customize_and_run_template
|
11
11
|
from fractal_server.app.db import get_sync_db
|
12
12
|
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
@@ -233,7 +233,7 @@ def collect_local(
|
|
233
233
|
activity = add_commit_refresh(obj=activity, db=db)
|
234
234
|
|
235
235
|
logger.info("create_db_tasks_and_update_task_group - " "start")
|
236
|
-
|
236
|
+
create_db_tasks_and_update_task_group_sync(
|
237
237
|
task_list=task_list,
|
238
238
|
task_group_id=task_group.id,
|
239
239
|
db=db,
|
{fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/collect.py
RENAMED
@@ -6,7 +6,7 @@ from typing import Optional
|
|
6
6
|
|
7
7
|
from ..utils_background import _prepare_tasks_metadata
|
8
8
|
from ..utils_background import fail_and_cleanup
|
9
|
-
from ..utils_database import
|
9
|
+
from ..utils_database import create_db_tasks_and_update_task_group_sync
|
10
10
|
from fractal_server.app.db import get_sync_db
|
11
11
|
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
12
12
|
from fractal_server.app.models.v2 import TaskGroupV2
|
@@ -265,7 +265,7 @@ def collect_ssh(
|
|
265
265
|
logger.info("_prepare_tasks_metadata - end")
|
266
266
|
|
267
267
|
logger.info("create_db_tasks_and_update_task_group - " "start")
|
268
|
-
|
268
|
+
create_db_tasks_and_update_task_group_sync(
|
269
269
|
task_list=task_list,
|
270
270
|
task_group_id=task_group.id,
|
271
271
|
db=db,
|
{fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_database.py
RENAMED
@@ -1,3 +1,4 @@
|
|
1
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
1
2
|
from sqlalchemy.orm import Session as DBSyncSession
|
2
3
|
|
3
4
|
from fractal_server.app.models.v2 import TaskGroupV2
|
@@ -5,7 +6,7 @@ from fractal_server.app.models.v2 import TaskV2
|
|
5
6
|
from fractal_server.app.schemas.v2 import TaskCreateV2
|
6
7
|
|
7
8
|
|
8
|
-
def
|
9
|
+
def create_db_tasks_and_update_task_group_sync(
|
9
10
|
*,
|
10
11
|
task_group_id: int,
|
11
12
|
task_list: list[TaskCreateV2],
|
@@ -30,3 +31,30 @@ def create_db_tasks_and_update_task_group(
|
|
30
31
|
db.refresh(task_group)
|
31
32
|
|
32
33
|
return task_group
|
34
|
+
|
35
|
+
|
36
|
+
async def create_db_tasks_and_update_task_group_async(
|
37
|
+
*,
|
38
|
+
task_group_id: int,
|
39
|
+
task_list: list[TaskCreateV2],
|
40
|
+
db: AsyncSession,
|
41
|
+
) -> TaskGroupV2:
|
42
|
+
"""
|
43
|
+
Create a `TaskGroupV2` with N `TaskV2`s, and insert them into the database.
|
44
|
+
|
45
|
+
Arguments:
|
46
|
+
task_group_id: ID of an existing `TaskGroupV2` object.
|
47
|
+
task_list: List of `TaskCreateV2` objects to be inserted into the db.
|
48
|
+
db: Synchronous database session
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
Updated `TaskGroupV2` object.
|
52
|
+
"""
|
53
|
+
actual_task_list = [TaskV2(**task.model_dump()) for task in task_list]
|
54
|
+
task_group = await db.get(TaskGroupV2, task_group_id)
|
55
|
+
task_group.task_list = actual_task_list
|
56
|
+
db.add(task_group)
|
57
|
+
await db.commit()
|
58
|
+
await db.refresh(task_group)
|
59
|
+
|
60
|
+
return task_group
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "fractal-server"
|
3
|
-
version = "2.14.
|
3
|
+
version = "2.14.0a20"
|
4
4
|
description = "Backend component of the Fractal analytics platform"
|
5
5
|
authors = [
|
6
6
|
{ name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
|
@@ -95,7 +95,7 @@ filterwarnings = [
|
|
95
95
|
markers = ["container", "ssh"]
|
96
96
|
|
97
97
|
[tool.bumpver]
|
98
|
-
current_version = "2.14.
|
98
|
+
current_version = "2.14.0a20"
|
99
99
|
version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
|
100
100
|
commit_message = "bump version {old_version} -> {new_version}"
|
101
101
|
commit = true
|
@@ -1 +0,0 @@
|
|
1
|
-
__VERSION__ = "2.14.0a18"
|