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.
Files changed (215) hide show
  1. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/PKG-INFO +1 -1
  2. fractal_server-2.14.0a20/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_collection_custom.py +4 -9
  4. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/base_runner.py +19 -18
  5. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/local/runner.py +2 -8
  6. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +45 -17
  7. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/remote.py +21 -35
  8. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_ssh/runner.py +22 -19
  9. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_sudo/runner.py +6 -2
  10. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/task_files.py +16 -6
  11. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/collect.py +2 -2
  12. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/collect.py +2 -2
  13. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_database.py +29 -1
  14. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/pyproject.toml +2 -2
  15. fractal_server-2.14.0a18/fractal_server/__init__.py +0 -1
  16. fractal_server-2.14.0a18/fractal_server/app/runner/executors/slurm_common/_handle_exception_proxy.py +0 -17
  17. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/LICENSE +0 -0
  18. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/README.md +0 -0
  19. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/__main__.py +0 -0
  20. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/alembic.ini +0 -0
  21. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/__init__.py +0 -0
  22. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/db/__init__.py +0 -0
  23. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/history/__init__.py +0 -0
  24. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/__init__.py +0 -0
  25. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/linkusergroup.py +0 -0
  26. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/linkuserproject.py +0 -0
  27. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/security.py +0 -0
  28. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/user_settings.py +0 -0
  29. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/__init__.py +0 -0
  30. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/accounting.py +0 -0
  31. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/dataset.py +0 -0
  32. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/history.py +0 -0
  33. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/job.py +0 -0
  34. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/project.py +0 -0
  35. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/task.py +0 -0
  36. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/task_group.py +0 -0
  37. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/workflow.py +0 -0
  38. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/models/v2/workflowtask.py +0 -0
  39. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/__init__.py +0 -0
  40. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/__init__.py +0 -0
  41. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  42. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  43. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  44. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/job.py +0 -0
  45. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/project.py +0 -0
  46. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/task.py +0 -0
  47. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  48. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  49. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/__init__.py +0 -0
  50. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  51. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  52. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  53. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  54. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  55. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  56. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/history.py +0 -0
  57. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/images.py +0 -0
  58. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/job.py +0 -0
  59. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/project.py +0 -0
  60. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  61. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/submit.py +0 -0
  62. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task.py +0 -0
  63. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  64. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  65. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  66. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/verify_image_types.py +0 -0
  67. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  68. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  69. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  70. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/__init__.py +0 -0
  71. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  72. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/current_user.py +0 -0
  73. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/group.py +0 -0
  74. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/login.py +0 -0
  75. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/oauth.py +0 -0
  76. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/register.py +0 -0
  77. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/router.py +0 -0
  78. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/auth/users.py +0 -0
  79. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/__init__.py +0 -0
  80. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/_job.py +0 -0
  81. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/_runner.py +0 -0
  82. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  83. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/routes/pagination.py +0 -0
  84. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/__init__.py +0 -0
  85. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/components.py +0 -0
  86. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/compress_folder.py +0 -0
  87. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/exceptions.py +0 -0
  88. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/__init__.py +0 -0
  89. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/local/__init__.py +0 -0
  90. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/local/get_local_config.py +0 -0
  91. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/__init__.py +0 -0
  92. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/_batching.py +0 -0
  93. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/_job_states.py +0 -0
  94. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/_slurm_config.py +0 -0
  95. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/get_slurm_config.py +0 -0
  96. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  97. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_common/utils_executors.py +0 -0
  98. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_ssh/__init__.py +0 -0
  99. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_sudo/__init__.py +0 -0
  100. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  101. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/extract_archive.py +0 -0
  102. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/filenames.py +0 -0
  103. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/run_subprocess.py +0 -0
  104. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/set_start_and_last_task_index.py +0 -0
  105. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/shutdown.py +0 -0
  106. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/__init__.py +0 -0
  107. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/_local.py +0 -0
  108. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/_slurm_ssh.py +0 -0
  109. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/_slurm_sudo.py +0 -0
  110. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/db_tools.py +0 -0
  111. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/deduplicate_list.py +0 -0
  112. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/merge_outputs.py +0 -0
  113. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/runner.py +0 -0
  114. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/runner_functions.py +0 -0
  115. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/runner_functions_low_level.py +0 -0
  116. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/submit_workflow.py +0 -0
  117. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/v2/task_interface.py +0 -0
  118. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/runner/versions.py +0 -0
  119. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/__init__.py +0 -0
  120. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/_filter_validators.py +0 -0
  121. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/_validators.py +0 -0
  122. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/user.py +0 -0
  123. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/user_group.py +0 -0
  124. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/user_settings.py +0 -0
  125. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/__init__.py +0 -0
  126. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/accounting.py +0 -0
  127. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/dataset.py +0 -0
  128. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/dumps.py +0 -0
  129. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/history.py +0 -0
  130. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/job.py +0 -0
  131. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/manifest.py +0 -0
  132. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/project.py +0 -0
  133. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  134. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/task.py +0 -0
  135. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  136. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/task_group.py +0 -0
  137. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/workflow.py +0 -0
  138. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  139. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/security/__init__.py +0 -0
  140. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/security/signup_email.py +0 -0
  141. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/app/user_settings.py +0 -0
  142. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/config.py +0 -0
  143. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/data_migrations/README.md +0 -0
  144. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/data_migrations/tools.py +0 -0
  145. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/gunicorn_fractal.py +0 -0
  146. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/images/__init__.py +0 -0
  147. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/images/models.py +0 -0
  148. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/images/tools.py +0 -0
  149. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/logger.py +0 -0
  150. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/main.py +0 -0
  151. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/env.py +0 -0
  152. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/naming_convention.py +0 -0
  153. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  154. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  155. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  156. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  157. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  158. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  159. {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
  160. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  161. {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
  162. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  163. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  164. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  165. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  166. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  167. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  168. {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
  169. {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
  170. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  171. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  172. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  173. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  174. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  175. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  176. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  177. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  178. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  179. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  180. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  181. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  182. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  183. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  184. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  185. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  186. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  187. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/py.typed +0 -0
  188. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/ssh/__init__.py +0 -0
  189. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/ssh/_fabric.py +0 -0
  190. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/string_tools.py +0 -0
  191. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/syringe.py +0 -0
  192. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/__init__.py +0 -0
  193. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/utils.py +0 -0
  194. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/__init__.py +0 -0
  195. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/__init__.py +0 -0
  196. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/_utils.py +0 -0
  197. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  198. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  199. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  200. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  201. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  202. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  203. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  204. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  205. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  206. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  207. {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
  208. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  209. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_background.py +0 -0
  210. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  211. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  212. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/tasks/v2/utils_templates.py +0 -0
  213. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/urls.py +0 -0
  214. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/utils.py +0 -0
  215. {fractal_server-2.14.0a18 → fractal_server-2.14.0a20}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fractal-server
3
- Version: 2.14.0a18
3
+ Version: 2.14.0a20
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License: BSD-3-Clause
6
6
  Author: Tommaso Comparin
@@ -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
- create_db_tasks_and_update_task_group,
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), # FIXME: using both sync/async
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 = create_db_tasks_and_update_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=db_sync,
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
- Dictionary of parameters. Must include `zarr_urls` key.
49
- history_item_id:
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
- list_parameters:
73
- List of dictionaries of parameters. Each one must include a
74
- `zarr_url` key.
75
- history_item_id:
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 `multi_submit` method
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 shutdown(self):
44
- logger.debug("Now shut LocalRunner.executor down")
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
- # FIXME: Fail for empty list
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
- exception = _handle_exception_proxy(output)
360
- return None, exception
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} (FIXME)")
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(slurm_job)
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
- time.sleep(self.poll_interval)
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} (FIXME)")
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(slurm_job)
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
- typ, value, tb = sys.exc_info()
150
- tb = tb.tb_next
151
- exc_proxy = ExceptionProxy(
152
- typ,
153
- "".join(traceback.format_exception(typ, value, tb)),
154
- *e.args,
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
- result = False, exc_proxy
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 compressed subfolder archive (locally)
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
- # Uncompress archive (remotely)
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.warning(f"{tarfile_path_remote} already exists!\n {str(e)}")
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
- stdout = self.fractal_ssh.run_command(cmd=tar_command)
142
- print(stdout)
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
- if Path(tarfile_path_local).exists():
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.info(f"[_copy_files_from_remote_to_local] {job.slurm_job_id=}")
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(
@@ -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(order: Union[int, str], task_name: str) -> str:
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
- Group all file paths pertaining to a task FIXME
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"
@@ -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 create_db_tasks_and_update_task_group
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
- create_db_tasks_and_update_task_group(
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,
@@ -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 create_db_tasks_and_update_task_group
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
- create_db_tasks_and_update_task_group(
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,
@@ -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 create_db_tasks_and_update_task_group(
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.0a18"
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.0a18"
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"