fractal-server 2.14.0a12__py3-none-any.whl → 2.14.0a14__py3-none-any.whl
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/__init__.py +1 -1
- fractal_server/app/models/linkusergroup.py +6 -2
- fractal_server/app/models/v2/dataset.py +1 -1
- fractal_server/app/models/v2/job.py +7 -3
- fractal_server/app/models/v2/task_group.py +2 -2
- fractal_server/app/models/v2/workflow.py +1 -1
- fractal_server/app/models/v2/workflowtask.py +1 -1
- fractal_server/app/routes/admin/v2/task_group.py +0 -17
- fractal_server/app/routes/api/v2/dataset.py +0 -8
- fractal_server/app/routes/api/v2/history.py +112 -27
- fractal_server/app/routes/api/v2/images.py +16 -14
- fractal_server/app/routes/api/v2/project.py +0 -52
- fractal_server/app/routes/api/v2/task_group.py +0 -17
- fractal_server/app/routes/api/v2/workflow.py +0 -8
- fractal_server/app/routes/auth/group.py +0 -16
- fractal_server/app/runner/executors/base_runner.py +5 -0
- fractal_server/app/runner/executors/local/runner.py +15 -7
- fractal_server/app/runner/executors/slurm_common/_handle_exception_proxy.py +17 -0
- fractal_server/app/runner/executors/slurm_common/base_slurm_runner.py +676 -0
- fractal_server/app/runner/executors/slurm_common/slurm_job_task_models.py +102 -0
- fractal_server/app/runner/executors/slurm_ssh/runner.py +110 -648
- fractal_server/app/runner/executors/slurm_sudo/runner.py +32 -661
- fractal_server/app/runner/task_files.py +20 -6
- fractal_server/app/runner/v2/_slurm_ssh.py +6 -6
- fractal_server/app/runner/v2/_slurm_sudo.py +4 -4
- fractal_server/app/runner/v2/db_tools.py +1 -0
- fractal_server/app/runner/v2/runner.py +4 -0
- fractal_server/app/runner/v2/runner_functions.py +2 -2
- fractal_server/app/runner/v2/submit_workflow.py +7 -16
- fractal_server/app/schemas/v2/__init__.py +3 -1
- fractal_server/app/schemas/v2/history.py +27 -2
- fractal_server/config.py +6 -2
- fractal_server/images/tools.py +23 -0
- fractal_server/migrations/versions/5b6007027595_on_cascade.py +250 -0
- fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +2 -2
- fractal_server/tasks/v2/utils_background.py +0 -19
- {fractal_server-2.14.0a12.dist-info → fractal_server-2.14.0a14.dist-info}/METADATA +1 -1
- {fractal_server-2.14.0a12.dist-info → fractal_server-2.14.0a14.dist-info}/RECORD +41 -42
- fractal_server/app/runner/executors/slurm_common/_check_jobs_status.py +0 -77
- fractal_server/app/runner/executors/slurm_ssh/_check_job_status_ssh.py +0 -67
- fractal_server/app/runner/executors/slurm_ssh/_executor_wait_thread.py +0 -126
- fractal_server/app/runner/executors/slurm_ssh/_slurm_job.py +0 -116
- fractal_server/app/runner/executors/slurm_ssh/executor.py +0 -1386
- {fractal_server-2.14.0a12.dist-info → fractal_server-2.14.0a14.dist-info}/LICENSE +0 -0
- {fractal_server-2.14.0a12.dist-info → fractal_server-2.14.0a14.dist-info}/WHEEL +0 -0
- {fractal_server-2.14.0a12.dist-info → fractal_server-2.14.0a14.dist-info}/entry_points.txt +0 -0
@@ -34,6 +34,7 @@ class TaskFiles(BaseModel):
|
|
34
34
|
|
35
35
|
# Per-single-component
|
36
36
|
component: Optional[str] = None
|
37
|
+
prefix: Optional[str] = None
|
37
38
|
|
38
39
|
def _check_component(self):
|
39
40
|
if self.component is None:
|
@@ -55,46 +56,55 @@ class TaskFiles(BaseModel):
|
|
55
56
|
def wftask_subfolder_local(self) -> Path:
|
56
57
|
return self.root_dir_local / self.subfolder_name
|
57
58
|
|
59
|
+
@property
|
60
|
+
def prefix_component(self):
|
61
|
+
if self.prefix is None:
|
62
|
+
return self.component
|
63
|
+
else:
|
64
|
+
return f"{self.prefix}-{self.component}"
|
65
|
+
|
58
66
|
@property
|
59
67
|
def log_file_local(self) -> str:
|
60
68
|
self._check_component()
|
61
69
|
return (
|
62
|
-
self.wftask_subfolder_local / f"{self.
|
70
|
+
self.wftask_subfolder_local / f"{self.prefix_component}-log.txt"
|
63
71
|
).as_posix()
|
64
72
|
|
65
73
|
@property
|
66
74
|
def log_file_remote(self) -> str:
|
67
75
|
self._check_component()
|
68
76
|
return (
|
69
|
-
self.wftask_subfolder_remote / f"{self.
|
77
|
+
self.wftask_subfolder_remote / f"{self.prefix_component}-log.txt"
|
70
78
|
).as_posix()
|
71
79
|
|
72
80
|
@property
|
73
81
|
def args_file_local(self) -> str:
|
74
82
|
self._check_component()
|
75
83
|
return (
|
76
|
-
self.wftask_subfolder_local / f"{self.
|
84
|
+
self.wftask_subfolder_local / f"{self.prefix_component}-args.json"
|
77
85
|
).as_posix()
|
78
86
|
|
79
87
|
@property
|
80
88
|
def args_file_remote(self) -> str:
|
81
89
|
self._check_component()
|
82
90
|
return (
|
83
|
-
self.wftask_subfolder_remote / f"{self.
|
91
|
+
self.wftask_subfolder_remote / f"{self.prefix_component}-args.json"
|
84
92
|
).as_posix()
|
85
93
|
|
86
94
|
@property
|
87
95
|
def metadiff_file_local(self) -> str:
|
88
96
|
self._check_component()
|
89
97
|
return (
|
90
|
-
self.wftask_subfolder_local
|
98
|
+
self.wftask_subfolder_local
|
99
|
+
/ f"{self.prefix_component}-metadiff.json"
|
91
100
|
).as_posix()
|
92
101
|
|
93
102
|
@property
|
94
103
|
def metadiff_file_remote(self) -> str:
|
95
104
|
self._check_component()
|
96
105
|
return (
|
97
|
-
self.wftask_subfolder_remote
|
106
|
+
self.wftask_subfolder_remote
|
107
|
+
/ f"{self.prefix_component}-metadiff.json"
|
98
108
|
).as_posix()
|
99
109
|
|
100
110
|
@property
|
@@ -104,3 +114,7 @@ class TaskFiles(BaseModel):
|
|
104
114
|
metadiff_file_remote=self.metadiff_file_remote,
|
105
115
|
log_file_remote=self.log_file_remote,
|
106
116
|
)
|
117
|
+
|
118
|
+
|
119
|
+
SUBMIT_PREFIX = "non_par"
|
120
|
+
MULTISUBMIT_PREFIX = "par"
|
@@ -24,7 +24,7 @@ from ...models.v2 import DatasetV2
|
|
24
24
|
from ...models.v2 import WorkflowV2
|
25
25
|
from ..exceptions import JobExecutionError
|
26
26
|
from ..executors.slurm_common.get_slurm_config import get_slurm_config
|
27
|
-
from ..executors.slurm_ssh.
|
27
|
+
from ..executors.slurm_ssh.runner import SlurmSSHRunner
|
28
28
|
from ..set_start_and_last_task_index import set_start_and_last_task_index
|
29
29
|
from .runner import execute_tasks_v2
|
30
30
|
from fractal_server.images.models import AttributeFiltersType
|
@@ -76,18 +76,18 @@ def process_workflow(
|
|
76
76
|
logger.error(error_msg)
|
77
77
|
raise JobExecutionError(info=error_msg)
|
78
78
|
|
79
|
-
with
|
79
|
+
with SlurmSSHRunner(
|
80
80
|
fractal_ssh=fractal_ssh,
|
81
|
-
|
82
|
-
|
81
|
+
root_dir_local=workflow_dir_local,
|
82
|
+
root_dir_remote=workflow_dir_remote,
|
83
83
|
common_script_lines=worker_init,
|
84
|
-
) as
|
84
|
+
) as runner:
|
85
85
|
execute_tasks_v2(
|
86
86
|
wf_task_list=workflow.task_list[
|
87
87
|
first_task_index : (last_task_index + 1)
|
88
88
|
],
|
89
89
|
dataset=dataset,
|
90
|
-
runner=
|
90
|
+
runner=runner,
|
91
91
|
workflow_dir_local=workflow_dir_local,
|
92
92
|
workflow_dir_remote=workflow_dir_remote,
|
93
93
|
logger_name=logger_name,
|
@@ -22,7 +22,7 @@ from typing import Optional
|
|
22
22
|
from ...models.v2 import DatasetV2
|
23
23
|
from ...models.v2 import WorkflowV2
|
24
24
|
from ..executors.slurm_common.get_slurm_config import get_slurm_config
|
25
|
-
from ..executors.slurm_sudo.runner import
|
25
|
+
from ..executors.slurm_sudo.runner import SudoSlurmRunner
|
26
26
|
from ..set_start_and_last_task_index import set_start_and_last_task_index
|
27
27
|
from .runner import execute_tasks_v2
|
28
28
|
from fractal_server.images.models import AttributeFiltersType
|
@@ -66,20 +66,20 @@ def process_workflow(
|
|
66
66
|
if isinstance(worker_init, str):
|
67
67
|
worker_init = worker_init.split("\n")
|
68
68
|
|
69
|
-
with
|
69
|
+
with SudoSlurmRunner(
|
70
70
|
slurm_user=slurm_user,
|
71
71
|
user_cache_dir=user_cache_dir,
|
72
72
|
root_dir_local=workflow_dir_local,
|
73
73
|
root_dir_remote=workflow_dir_remote,
|
74
74
|
common_script_lines=worker_init,
|
75
75
|
slurm_account=slurm_account,
|
76
|
-
) as
|
76
|
+
) as runner:
|
77
77
|
execute_tasks_v2(
|
78
78
|
wf_task_list=workflow.task_list[
|
79
79
|
first_task_index : (last_task_index + 1)
|
80
80
|
],
|
81
81
|
dataset=dataset,
|
82
|
-
runner=
|
82
|
+
runner=runner,
|
83
83
|
workflow_dir_local=workflow_dir_local,
|
84
84
|
workflow_dir_remote=workflow_dir_remote,
|
85
85
|
logger_name=logger_name,
|
@@ -126,6 +126,10 @@ def execute_tasks_v2(
|
|
126
126
|
db.commit()
|
127
127
|
db.refresh(history_run)
|
128
128
|
history_run_id = history_run.id
|
129
|
+
logger.debug(
|
130
|
+
f"Created {history_run_id=}, for "
|
131
|
+
f"{wftask.id=} and {dataset.id=}"
|
132
|
+
)
|
129
133
|
|
130
134
|
# TASK EXECUTION (V2)
|
131
135
|
if task.type in ["non_parallel", "converter_non_parallel"]:
|
@@ -372,7 +372,7 @@ def run_v2_task_compound(
|
|
372
372
|
root_dir_remote=workflow_dir_remote,
|
373
373
|
task_order=wftask.order,
|
374
374
|
task_name=wftask.task.name,
|
375
|
-
component=
|
375
|
+
component=_index_to_component(0),
|
376
376
|
)
|
377
377
|
|
378
378
|
runner_config_init = get_runner_config(
|
@@ -483,7 +483,7 @@ def run_v2_task_compound(
|
|
483
483
|
root_dir_remote=workflow_dir_remote,
|
484
484
|
task_order=wftask.order,
|
485
485
|
task_name=wftask.task.name,
|
486
|
-
component=
|
486
|
+
component=_index_to_component(ind),
|
487
487
|
)
|
488
488
|
for ind in range(len(parallelization_list))
|
489
489
|
]
|
@@ -27,7 +27,6 @@ from ...models.v2 import WorkflowV2
|
|
27
27
|
from ...schemas.v2 import JobStatusTypeV2
|
28
28
|
from ..exceptions import JobExecutionError
|
29
29
|
from ..exceptions import TaskExecutionError
|
30
|
-
from ..executors.slurm_sudo._subprocess_run_as_user import _mkdir_as_user
|
31
30
|
from ..filenames import WORKFLOW_LOG_FILENAME
|
32
31
|
from ._local import process_workflow as local_process_workflow
|
33
32
|
from ._slurm_ssh import process_workflow as slurm_ssh_process_workflow
|
@@ -170,35 +169,27 @@ def submit_workflow(
|
|
170
169
|
return
|
171
170
|
|
172
171
|
try:
|
173
|
-
# Create WORKFLOW_DIR_LOCAL
|
174
|
-
if FRACTAL_RUNNER_BACKEND == "slurm":
|
175
|
-
original_umask = os.umask(0)
|
176
|
-
WORKFLOW_DIR_LOCAL.mkdir(parents=True, mode=0o755)
|
177
|
-
os.umask(original_umask)
|
178
|
-
else:
|
179
|
-
WORKFLOW_DIR_LOCAL.mkdir(parents=True)
|
180
|
-
|
181
|
-
# Define and create WORKFLOW_DIR_REMOTE
|
172
|
+
# Create WORKFLOW_DIR_LOCAL and define WORKFLOW_DIR_REMOTE
|
182
173
|
if FRACTAL_RUNNER_BACKEND == "local":
|
174
|
+
WORKFLOW_DIR_LOCAL.mkdir(parents=True)
|
183
175
|
WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
|
184
176
|
elif FRACTAL_RUNNER_BACKEND == "slurm":
|
177
|
+
original_umask = os.umask(0)
|
178
|
+
WORKFLOW_DIR_LOCAL.mkdir(parents=True, mode=0o755)
|
179
|
+
os.umask(original_umask)
|
185
180
|
WORKFLOW_DIR_REMOTE = (
|
186
181
|
Path(user_cache_dir) / WORKFLOW_DIR_LOCAL.name
|
187
182
|
)
|
188
|
-
_mkdir_as_user(
|
189
|
-
folder=str(WORKFLOW_DIR_REMOTE), user=slurm_user
|
190
|
-
)
|
191
183
|
elif FRACTAL_RUNNER_BACKEND == "slurm_ssh":
|
192
|
-
|
184
|
+
WORKFLOW_DIR_LOCAL.mkdir(parents=True)
|
193
185
|
WORKFLOW_DIR_REMOTE = (
|
194
186
|
Path(user_settings.ssh_jobs_dir) / WORKFLOW_DIR_LOCAL.name
|
195
187
|
)
|
196
188
|
else:
|
197
|
-
|
189
|
+
raise ValueError(
|
198
190
|
"Invalid FRACTAL_RUNNER_BACKEND="
|
199
191
|
f"{settings.FRACTAL_RUNNER_BACKEND}."
|
200
192
|
)
|
201
|
-
|
202
193
|
except Exception as e:
|
203
194
|
error_type = type(e).__name__
|
204
195
|
fail_job(
|
@@ -10,11 +10,13 @@ from .dumps import TaskDumpV2 # noqa F401
|
|
10
10
|
from .dumps import TaskGroupDumpV2 # noqa F401
|
11
11
|
from .dumps import WorkflowDumpV2 # noqa F401
|
12
12
|
from .dumps import WorkflowTaskDumpV2 # noqa F401
|
13
|
+
from .history import HistoryRunRead # noqa F401
|
13
14
|
from .history import HistoryRunReadAggregated # noqa F401
|
14
15
|
from .history import HistoryUnitRead # noqa F401
|
15
16
|
from .history import HistoryUnitStatus # noqa F401
|
17
|
+
from .history import HistoryUnitStatusQuery # noqa F401
|
16
18
|
from .history import ImageLogsRequest # noqa F401
|
17
|
-
from .history import
|
19
|
+
from .history import SingleImageWithStatus # noqa F401
|
18
20
|
from .job import JobCreateV2 # noqa F401
|
19
21
|
from .job import JobReadV2 # noqa F401
|
20
22
|
from .job import JobStatusTypeV2 # noqa F401
|
@@ -7,6 +7,8 @@ from pydantic import AwareDatetime
|
|
7
7
|
from pydantic import BaseModel
|
8
8
|
from pydantic import field_serializer
|
9
9
|
|
10
|
+
from ....images import SingleImage
|
11
|
+
|
10
12
|
|
11
13
|
class HistoryUnitStatus(str, Enum):
|
12
14
|
"""
|
@@ -23,6 +25,15 @@ class HistoryUnitStatus(str, Enum):
|
|
23
25
|
FAILED = "failed"
|
24
26
|
|
25
27
|
|
28
|
+
class HistoryUnitStatusQuery(str, Enum):
|
29
|
+
|
30
|
+
SUBMITTED = "submitted"
|
31
|
+
DONE = "done"
|
32
|
+
FAILED = "failed"
|
33
|
+
|
34
|
+
UNSET = "unset"
|
35
|
+
|
36
|
+
|
26
37
|
class HistoryUnitRead(BaseModel):
|
27
38
|
id: int
|
28
39
|
logfile: Optional[str] = None
|
@@ -30,6 +41,21 @@ class HistoryUnitRead(BaseModel):
|
|
30
41
|
zarr_urls: list[str]
|
31
42
|
|
32
43
|
|
44
|
+
class HistoryRunRead(BaseModel):
|
45
|
+
id: int
|
46
|
+
dataset_id: int
|
47
|
+
workflowtask_id: Optional[int] = None
|
48
|
+
workflowtask_dump: dict[str, Any]
|
49
|
+
task_group_dump: dict[str, Any]
|
50
|
+
timestamp_started: AwareDatetime
|
51
|
+
status: HistoryUnitStatus
|
52
|
+
num_available_images: int
|
53
|
+
|
54
|
+
@field_serializer("timestamp_started")
|
55
|
+
def serialize_datetime(v: datetime) -> str:
|
56
|
+
return v.isoformat()
|
57
|
+
|
58
|
+
|
33
59
|
class HistoryRunReadAggregated(BaseModel):
|
34
60
|
id: int
|
35
61
|
timestamp_started: AwareDatetime
|
@@ -49,6 +75,5 @@ class ImageLogsRequest(BaseModel):
|
|
49
75
|
zarr_url: str
|
50
76
|
|
51
77
|
|
52
|
-
class
|
53
|
-
zarr_url: str
|
78
|
+
class SingleImageWithStatus(SingleImage):
|
54
79
|
status: Optional[HistoryUnitStatus] = None
|
fractal_server/config.py
CHANGED
@@ -489,8 +489,12 @@ class Settings(BaseSettings):
|
|
489
489
|
FRACTAL_SLURM_POLL_INTERVAL: int = 5
|
490
490
|
"""
|
491
491
|
Interval to wait (in seconds) before checking whether unfinished job are
|
492
|
-
still running on SLURM
|
493
|
-
|
492
|
+
still running on SLURM.
|
493
|
+
"""
|
494
|
+
|
495
|
+
FRACTAL_SLURM_INTERVAL_BEFORE_RETRIEVAL: int = 2
|
496
|
+
"""
|
497
|
+
FIXME: this is a workaround, we are still investigating.
|
494
498
|
"""
|
495
499
|
|
496
500
|
FRACTAL_SLURM_SBATCH_SLEEP: float = 0
|
fractal_server/images/tools.py
CHANGED
@@ -121,3 +121,26 @@ def merge_type_filters(
|
|
121
121
|
merged_dict = task_input_types
|
122
122
|
merged_dict.update(wftask_type_filters)
|
123
123
|
return merged_dict
|
124
|
+
|
125
|
+
|
126
|
+
def aggregate_attributes(images: list[dict[str, Any]]) -> dict[str, list[Any]]:
|
127
|
+
"""
|
128
|
+
Given a list of images, this function returns a dictionary of all image
|
129
|
+
attributes, each mapped to a list of present values.
|
130
|
+
"""
|
131
|
+
attributes = {}
|
132
|
+
for image in images:
|
133
|
+
for k, v in image["attributes"].items():
|
134
|
+
attributes.setdefault(k, []).append(v)
|
135
|
+
for k, v in attributes.items():
|
136
|
+
attributes[k] = list(set(v))
|
137
|
+
return attributes
|
138
|
+
|
139
|
+
|
140
|
+
def aggregate_types(images: list[dict[str, Any]]) -> list[str]:
|
141
|
+
"""
|
142
|
+
Given a list of images, this function returns a list of all image types.
|
143
|
+
"""
|
144
|
+
return list(
|
145
|
+
set(type for image in images for type in image["types"].keys())
|
146
|
+
)
|
@@ -0,0 +1,250 @@
|
|
1
|
+
"""on cascade
|
2
|
+
|
3
|
+
Revision ID: 5b6007027595
|
4
|
+
Revises: af1ef1c83c9b
|
5
|
+
Create Date: 2025-04-02 17:03:59.542921
|
6
|
+
|
7
|
+
"""
|
8
|
+
from alembic import op
|
9
|
+
|
10
|
+
|
11
|
+
# revision identifiers, used by Alembic.
|
12
|
+
revision = "5b6007027595"
|
13
|
+
down_revision = "af1ef1c83c9b"
|
14
|
+
branch_labels = None
|
15
|
+
depends_on = None
|
16
|
+
|
17
|
+
|
18
|
+
def upgrade() -> None:
|
19
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
20
|
+
with op.batch_alter_table("datasetv2", schema=None) as batch_op:
|
21
|
+
batch_op.drop_constraint(
|
22
|
+
"fk_datasetv2_project_id_projectv2", type_="foreignkey"
|
23
|
+
)
|
24
|
+
batch_op.create_foreign_key(
|
25
|
+
batch_op.f("fk_datasetv2_project_id_projectv2"),
|
26
|
+
"projectv2",
|
27
|
+
["project_id"],
|
28
|
+
["id"],
|
29
|
+
ondelete="CASCADE",
|
30
|
+
)
|
31
|
+
|
32
|
+
with op.batch_alter_table("jobv2", schema=None) as batch_op:
|
33
|
+
batch_op.drop_constraint(
|
34
|
+
"fk_jobv2_dataset_id_datasetv2", type_="foreignkey"
|
35
|
+
)
|
36
|
+
batch_op.drop_constraint(
|
37
|
+
"fk_jobv2_workflow_id_workflowv2", type_="foreignkey"
|
38
|
+
)
|
39
|
+
batch_op.drop_constraint(
|
40
|
+
"fk_jobv2_project_id_projectv2", type_="foreignkey"
|
41
|
+
)
|
42
|
+
batch_op.create_foreign_key(
|
43
|
+
batch_op.f("fk_jobv2_project_id_projectv2"),
|
44
|
+
"projectv2",
|
45
|
+
["project_id"],
|
46
|
+
["id"],
|
47
|
+
ondelete="SET NULL",
|
48
|
+
)
|
49
|
+
batch_op.create_foreign_key(
|
50
|
+
batch_op.f("fk_jobv2_dataset_id_datasetv2"),
|
51
|
+
"datasetv2",
|
52
|
+
["dataset_id"],
|
53
|
+
["id"],
|
54
|
+
ondelete="SET NULL",
|
55
|
+
)
|
56
|
+
batch_op.create_foreign_key(
|
57
|
+
batch_op.f("fk_jobv2_workflow_id_workflowv2"),
|
58
|
+
"workflowv2",
|
59
|
+
["workflow_id"],
|
60
|
+
["id"],
|
61
|
+
ondelete="SET NULL",
|
62
|
+
)
|
63
|
+
|
64
|
+
with op.batch_alter_table("linkusergroup", schema=None) as batch_op:
|
65
|
+
batch_op.drop_constraint(
|
66
|
+
"fk_linkusergroup_group_id_usergroup", type_="foreignkey"
|
67
|
+
)
|
68
|
+
batch_op.drop_constraint(
|
69
|
+
"fk_linkusergroup_user_id_user_oauth", type_="foreignkey"
|
70
|
+
)
|
71
|
+
batch_op.create_foreign_key(
|
72
|
+
batch_op.f("fk_linkusergroup_group_id_usergroup"),
|
73
|
+
"usergroup",
|
74
|
+
["group_id"],
|
75
|
+
["id"],
|
76
|
+
ondelete="CASCADE",
|
77
|
+
)
|
78
|
+
batch_op.create_foreign_key(
|
79
|
+
batch_op.f("fk_linkusergroup_user_id_user_oauth"),
|
80
|
+
"user_oauth",
|
81
|
+
["user_id"],
|
82
|
+
["id"],
|
83
|
+
ondelete="CASCADE",
|
84
|
+
)
|
85
|
+
|
86
|
+
with op.batch_alter_table("taskgroupactivityv2", schema=None) as batch_op:
|
87
|
+
batch_op.drop_constraint(
|
88
|
+
"fk_taskgroupactivityv2_taskgroupv2_id_taskgroupv2",
|
89
|
+
type_="foreignkey",
|
90
|
+
)
|
91
|
+
batch_op.create_foreign_key(
|
92
|
+
batch_op.f("fk_taskgroupactivityv2_taskgroupv2_id_taskgroupv2"),
|
93
|
+
"taskgroupv2",
|
94
|
+
["taskgroupv2_id"],
|
95
|
+
["id"],
|
96
|
+
ondelete="SET NULL",
|
97
|
+
)
|
98
|
+
|
99
|
+
with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
|
100
|
+
batch_op.drop_constraint(
|
101
|
+
"fk_taskgroupv2_user_group_id_usergroup", type_="foreignkey"
|
102
|
+
)
|
103
|
+
batch_op.create_foreign_key(
|
104
|
+
batch_op.f("fk_taskgroupv2_user_group_id_usergroup"),
|
105
|
+
"usergroup",
|
106
|
+
["user_group_id"],
|
107
|
+
["id"],
|
108
|
+
ondelete="SET NULL",
|
109
|
+
)
|
110
|
+
|
111
|
+
with op.batch_alter_table("workflowtaskv2", schema=None) as batch_op:
|
112
|
+
batch_op.drop_constraint(
|
113
|
+
"fk_workflowtaskv2_workflow_id_workflowv2", type_="foreignkey"
|
114
|
+
)
|
115
|
+
batch_op.create_foreign_key(
|
116
|
+
batch_op.f("fk_workflowtaskv2_workflow_id_workflowv2"),
|
117
|
+
"workflowv2",
|
118
|
+
["workflow_id"],
|
119
|
+
["id"],
|
120
|
+
ondelete="CASCADE",
|
121
|
+
)
|
122
|
+
|
123
|
+
with op.batch_alter_table("workflowv2", schema=None) as batch_op:
|
124
|
+
batch_op.drop_constraint(
|
125
|
+
"fk_workflowv2_project_id_projectv2", type_="foreignkey"
|
126
|
+
)
|
127
|
+
batch_op.create_foreign_key(
|
128
|
+
batch_op.f("fk_workflowv2_project_id_projectv2"),
|
129
|
+
"projectv2",
|
130
|
+
["project_id"],
|
131
|
+
["id"],
|
132
|
+
ondelete="CASCADE",
|
133
|
+
)
|
134
|
+
|
135
|
+
# ### end Alembic commands ###
|
136
|
+
|
137
|
+
|
138
|
+
def downgrade() -> None:
|
139
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
140
|
+
with op.batch_alter_table("workflowv2", schema=None) as batch_op:
|
141
|
+
batch_op.drop_constraint(
|
142
|
+
batch_op.f("fk_workflowv2_project_id_projectv2"),
|
143
|
+
type_="foreignkey",
|
144
|
+
)
|
145
|
+
batch_op.create_foreign_key(
|
146
|
+
"fk_workflowv2_project_id_projectv2",
|
147
|
+
"projectv2",
|
148
|
+
["project_id"],
|
149
|
+
["id"],
|
150
|
+
)
|
151
|
+
|
152
|
+
with op.batch_alter_table("workflowtaskv2", schema=None) as batch_op:
|
153
|
+
batch_op.drop_constraint(
|
154
|
+
batch_op.f("fk_workflowtaskv2_workflow_id_workflowv2"),
|
155
|
+
type_="foreignkey",
|
156
|
+
)
|
157
|
+
batch_op.create_foreign_key(
|
158
|
+
"fk_workflowtaskv2_workflow_id_workflowv2",
|
159
|
+
"workflowv2",
|
160
|
+
["workflow_id"],
|
161
|
+
["id"],
|
162
|
+
)
|
163
|
+
|
164
|
+
with op.batch_alter_table("taskgroupv2", schema=None) as batch_op:
|
165
|
+
batch_op.drop_constraint(
|
166
|
+
batch_op.f("fk_taskgroupv2_user_group_id_usergroup"),
|
167
|
+
type_="foreignkey",
|
168
|
+
)
|
169
|
+
batch_op.create_foreign_key(
|
170
|
+
"fk_taskgroupv2_user_group_id_usergroup",
|
171
|
+
"usergroup",
|
172
|
+
["user_group_id"],
|
173
|
+
["id"],
|
174
|
+
)
|
175
|
+
|
176
|
+
with op.batch_alter_table("taskgroupactivityv2", schema=None) as batch_op:
|
177
|
+
batch_op.drop_constraint(
|
178
|
+
batch_op.f("fk_taskgroupactivityv2_taskgroupv2_id_taskgroupv2"),
|
179
|
+
type_="foreignkey",
|
180
|
+
)
|
181
|
+
batch_op.create_foreign_key(
|
182
|
+
"fk_taskgroupactivityv2_taskgroupv2_id_taskgroupv2",
|
183
|
+
"taskgroupv2",
|
184
|
+
["taskgroupv2_id"],
|
185
|
+
["id"],
|
186
|
+
)
|
187
|
+
|
188
|
+
with op.batch_alter_table("linkusergroup", schema=None) as batch_op:
|
189
|
+
batch_op.drop_constraint(
|
190
|
+
batch_op.f("fk_linkusergroup_user_id_user_oauth"),
|
191
|
+
type_="foreignkey",
|
192
|
+
)
|
193
|
+
batch_op.drop_constraint(
|
194
|
+
batch_op.f("fk_linkusergroup_group_id_usergroup"),
|
195
|
+
type_="foreignkey",
|
196
|
+
)
|
197
|
+
batch_op.create_foreign_key(
|
198
|
+
"fk_linkusergroup_user_id_user_oauth",
|
199
|
+
"user_oauth",
|
200
|
+
["user_id"],
|
201
|
+
["id"],
|
202
|
+
)
|
203
|
+
batch_op.create_foreign_key(
|
204
|
+
"fk_linkusergroup_group_id_usergroup",
|
205
|
+
"usergroup",
|
206
|
+
["group_id"],
|
207
|
+
["id"],
|
208
|
+
)
|
209
|
+
|
210
|
+
with op.batch_alter_table("jobv2", schema=None) as batch_op:
|
211
|
+
batch_op.drop_constraint(
|
212
|
+
batch_op.f("fk_jobv2_workflow_id_workflowv2"), type_="foreignkey"
|
213
|
+
)
|
214
|
+
batch_op.drop_constraint(
|
215
|
+
batch_op.f("fk_jobv2_dataset_id_datasetv2"), type_="foreignkey"
|
216
|
+
)
|
217
|
+
batch_op.drop_constraint(
|
218
|
+
batch_op.f("fk_jobv2_project_id_projectv2"), type_="foreignkey"
|
219
|
+
)
|
220
|
+
batch_op.create_foreign_key(
|
221
|
+
"fk_jobv2_project_id_projectv2",
|
222
|
+
"projectv2",
|
223
|
+
["project_id"],
|
224
|
+
["id"],
|
225
|
+
)
|
226
|
+
batch_op.create_foreign_key(
|
227
|
+
"fk_jobv2_workflow_id_workflowv2",
|
228
|
+
"workflowv2",
|
229
|
+
["workflow_id"],
|
230
|
+
["id"],
|
231
|
+
)
|
232
|
+
batch_op.create_foreign_key(
|
233
|
+
"fk_jobv2_dataset_id_datasetv2",
|
234
|
+
"datasetv2",
|
235
|
+
["dataset_id"],
|
236
|
+
["id"],
|
237
|
+
)
|
238
|
+
|
239
|
+
with op.batch_alter_table("datasetv2", schema=None) as batch_op:
|
240
|
+
batch_op.drop_constraint(
|
241
|
+
batch_op.f("fk_datasetv2_project_id_projectv2"), type_="foreignkey"
|
242
|
+
)
|
243
|
+
batch_op.create_foreign_key(
|
244
|
+
"fk_datasetv2_project_id_projectv2",
|
245
|
+
"projectv2",
|
246
|
+
["project_id"],
|
247
|
+
["id"],
|
248
|
+
)
|
249
|
+
|
250
|
+
# ### end Alembic commands ###
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"""new history items
|
2
2
|
|
3
3
|
Revision ID: fbce16ff4e47
|
4
|
-
Revises:
|
4
|
+
Revises: 5b6007027595
|
5
5
|
Create Date: 2025-03-14 15:25:01.083619
|
6
6
|
|
7
7
|
"""
|
@@ -12,7 +12,7 @@ from sqlalchemy.dialects import postgresql
|
|
12
12
|
|
13
13
|
# revision identifiers, used by Alembic.
|
14
14
|
revision = "fbce16ff4e47"
|
15
|
-
down_revision = "
|
15
|
+
down_revision = "5b6007027595"
|
16
16
|
branch_labels = None
|
17
17
|
depends_on = None
|
18
18
|
|
@@ -3,7 +3,6 @@ from typing import Optional
|
|
3
3
|
from typing import TypeVar
|
4
4
|
|
5
5
|
from sqlalchemy.orm import Session as DBSyncSession
|
6
|
-
from sqlmodel import select
|
7
6
|
|
8
7
|
from fractal_server.app.models.v2 import TaskGroupActivityV2
|
9
8
|
from fractal_server.app.models.v2 import TaskGroupV2
|
@@ -44,24 +43,6 @@ def fail_and_cleanup(
|
|
44
43
|
task_group_activity.log = get_current_log(log_file_path)
|
45
44
|
task_group_activity = add_commit_refresh(obj=task_group_activity, db=db)
|
46
45
|
if task_group_activity.action == TaskGroupActivityActionV2.COLLECT:
|
47
|
-
logger.info(f"Now delete TaskGroupV2 with {task_group.id=}")
|
48
|
-
|
49
|
-
logger.info("Start of TaskGroupActivityV2 cascade operations.")
|
50
|
-
stm = select(TaskGroupActivityV2).where(
|
51
|
-
TaskGroupActivityV2.taskgroupv2_id == task_group.id
|
52
|
-
)
|
53
|
-
res = db.execute(stm)
|
54
|
-
task_group_activity_list = res.scalars().all()
|
55
|
-
for task_group_activity in task_group_activity_list:
|
56
|
-
logger.info(
|
57
|
-
f"Setting TaskGroupActivityV2[{task_group_activity.id}]"
|
58
|
-
".taskgroupv2_id to None."
|
59
|
-
)
|
60
|
-
task_group_activity.taskgroupv2_id = None
|
61
|
-
db.add(task_group_activity)
|
62
|
-
logger.info("End of TaskGroupActivityV2 cascade operations.")
|
63
|
-
logger.info(f"TaskGroupV2 with {task_group.id=} deleted")
|
64
|
-
|
65
46
|
db.delete(task_group)
|
66
47
|
db.commit()
|
67
48
|
reset_logger_handlers(logger)
|