Skip to content

Commit aa193c7

Browse files
committed
move create study job function to job_service
1 parent 1d86dc3 commit aa193c7

File tree

3 files changed

+89
-76
lines changed

3 files changed

+89
-76
lines changed

services/api-server/src/simcore_service_api_server/_service_jobs.py

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from collections.abc import Callable
33
from dataclasses import dataclass
44
from pathlib import Path
5+
from uuid import UUID
56

67
from common_library.exclude import as_dict_exclude_none
78
from models_library.api_schemas_rpc_async_jobs.async_jobs import AsyncJobGet
@@ -10,8 +11,11 @@
1011
ProjectGet,
1112
ProjectPatch,
1213
)
14+
from models_library.api_schemas_webserver.projects_nodes import NodeOutputs
15+
from models_library.function_services_catalog.services import file_picker
1316
from models_library.products import ProductName
1417
from models_library.projects import ProjectID
18+
from models_library.projects_nodes import InputID, InputTypes
1519
from models_library.projects_nodes_io import NodeID
1620
from models_library.rest_pagination import (
1721
PageMetaInfoLimitOffset,
@@ -50,6 +54,10 @@
5054
create_new_project_for_job,
5155
)
5256
from .services_http.storage import StorageApi
57+
from .services_http.study_job_models_converters import (
58+
create_job_from_study,
59+
get_project_and_file_inputs_from_job_inputs,
60+
)
5361
from .services_http.webserver import AuthSession
5462
from .services_rpc.director_v2 import DirectorV2Service
5563
from .services_rpc.storage import StorageService
@@ -274,7 +282,7 @@ async def get_job(
274282

275283
async def delete_job_assets(
276284
self, job_parent_resource_name: RelativeResourceName, job_id: JobID
277-
):
285+
) -> None:
278286
"""Marks job project as hidden and deletes S3 assets associated it"""
279287
await self._web_rest_client.patch_project(
280288
project_id=job_id, patch_params=ProjectPatch(hidden=True)
@@ -325,7 +333,7 @@ async def inspect_solver_job(
325333
solver_key: SolverKeyId,
326334
version: VersionStr,
327335
job_id: JobID,
328-
):
336+
) -> JobStatus:
329337
assert solver_key # nosec
330338
assert version # nosec
331339
task = await self._director2_api.get_computation(
@@ -341,7 +349,7 @@ async def start_solver_job(
341349
version: VersionStr,
342350
job_id: JobID,
343351
pricing_spec: JobPricingSpecification | None,
344-
):
352+
) -> JobStatus:
345353
"""
346354
Raises ProjectAlreadyStartedError if the project is already started
347355
"""
@@ -364,3 +372,71 @@ async def start_solver_job(
364372
version=version,
365373
job_id=job_id,
366374
)
375+
376+
async def create_studies_job(
377+
self,
378+
*,
379+
study_id: StudyID,
380+
job_inputs: JobInputs,
381+
x_simcore_parent_project_uuid: ProjectID | None,
382+
x_simcore_parent_node_id: NodeID | None,
383+
hidden: bool,
384+
) -> Job:
385+
386+
project = await self._web_rest_client.clone_project(
387+
project_id=study_id,
388+
hidden=hidden,
389+
parent_project_uuid=x_simcore_parent_project_uuid,
390+
parent_node_id=x_simcore_parent_node_id,
391+
)
392+
job = create_job_from_study(
393+
study_key=study_id, project=project, job_inputs=job_inputs
394+
)
395+
396+
await self._web_rest_client.patch_project(
397+
project_id=job.id,
398+
patch_params=ProjectPatch(name=job.name),
399+
)
400+
401+
await self._web_rpc_client.mark_project_as_job(
402+
product_name=self.product_name,
403+
user_id=self.user_id,
404+
project_uuid=job.id,
405+
job_parent_resource_name=job.runner_name,
406+
storage_assets_deleted=False,
407+
)
408+
409+
project_inputs = await self._web_rest_client.get_project_inputs(
410+
project_id=project.uuid
411+
)
412+
413+
file_param_nodes = {}
414+
for node_id, node in project.workbench.items():
415+
if (
416+
node.key == file_picker.META.key
417+
and node.outputs is not None
418+
and len(node.outputs) == 0
419+
):
420+
file_param_nodes[node.label] = node_id
421+
422+
file_inputs: dict[InputID, InputTypes] = {}
423+
424+
(
425+
new_project_inputs,
426+
new_project_file_inputs,
427+
) = get_project_and_file_inputs_from_job_inputs(
428+
project_inputs, file_inputs, job_inputs
429+
)
430+
431+
for node_label, file_link in new_project_file_inputs.items():
432+
await self._web_rest_client.update_node_outputs(
433+
project_id=project.uuid,
434+
node_id=UUID(file_param_nodes[node_label]),
435+
new_node_outputs=NodeOutputs(outputs={"outFile": file_link}),
436+
)
437+
438+
if len(new_project_inputs) > 0:
439+
await self._web_rest_client.update_project_inputs(
440+
project_id=project.uuid, new_inputs=new_project_inputs
441+
)
442+
return job

services/api-server/src/simcore_service_api_server/api/routes/functions_routes.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,10 @@ async def run_function( # noqa: PLR0913
460460
study_job = await studies_jobs.create_study_job(
461461
study_id=to_run_function.project_id,
462462
job_inputs=JobInputs(values=joined_inputs or {}),
463-
webserver_api=webserver_api,
464-
wb_api_rpc=wb_api_rpc,
465463
url_for=url_for,
464+
job_service=job_service,
466465
x_simcore_parent_project_uuid=parent_project_uuid,
467466
x_simcore_parent_node_id=parent_node_id,
468-
user_id=user_id,
469-
product_name=product_name,
470467
)
471468
await studies_jobs.start_study_job(
472469
request=request,

services/api-server/src/simcore_service_api_server/api/routes/studies_jobs.py

Lines changed: 9 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import logging
22
from collections.abc import Callable
33
from typing import Annotated
4-
from uuid import UUID
54

65
from fastapi import APIRouter, Depends, Header, Query, Request, status
76
from fastapi.encoders import jsonable_encoder
87
from fastapi.responses import JSONResponse
98
from fastapi_pagination.api import create_page
10-
from models_library.api_schemas_webserver.projects import ProjectPatch
11-
from models_library.api_schemas_webserver.projects_nodes import NodeOutputs
129
from models_library.clusters import ClusterID
13-
from models_library.function_services_catalog.services import file_picker
1410
from models_library.projects import ProjectID
15-
from models_library.projects_nodes import InputID, InputTypes
1611
from models_library.projects_nodes_io import NodeID
1712
from pydantic import HttpUrl, PositiveInt
1813
from servicelib.logging_utils import log_context
@@ -42,17 +37,13 @@
4237
from ...services_http.solver_job_models_converters import create_jobstatus_from_task
4338
from ...services_http.storage import StorageApi
4439
from ...services_http.study_job_models_converters import (
45-
create_job_from_study,
4640
create_job_outputs_from_project_outputs,
47-
get_project_and_file_inputs_from_job_inputs,
4841
)
4942
from ...services_http.webserver import AuthSession
50-
from ...services_rpc.wb_api_server import WbApiRpcClient
5143
from ..dependencies.application import get_reverse_url_mapper
52-
from ..dependencies.authentication import get_current_user_id, get_product_name
44+
from ..dependencies.authentication import get_current_user_id
5345
from ..dependencies.services import get_api_client, get_job_service
5446
from ..dependencies.webserver_http import get_webserver_session
55-
from ..dependencies.webserver_rpc import get_wb_api_rpc_client
5647
from ._constants import (
5748
FMSG_CHANGELOG_CHANGED_IN_VERSION,
5849
FMSG_CHANGELOG_NEW_IN_VERSION,
@@ -121,27 +112,24 @@ async def list_study_jobs(
121112
async def create_study_job(
122113
study_id: StudyID,
123114
job_inputs: JobInputs,
124-
webserver_api: Annotated[AuthSession, Depends(get_webserver_session)],
125-
wb_api_rpc: Annotated[WbApiRpcClient, Depends(get_wb_api_rpc_client)],
126115
url_for: Annotated[Callable, Depends(get_reverse_url_mapper)],
127-
user_id: Annotated[PositiveInt, Depends(get_current_user_id)],
128-
product_name: Annotated[str, Depends(get_product_name)],
116+
job_service: Annotated[JobService, Depends(get_job_service)],
129117
hidden: Annotated[bool, Query()] = True, # noqa: FBT002
130118
x_simcore_parent_project_uuid: Annotated[ProjectID | None, Header()] = None,
131119
x_simcore_parent_node_id: Annotated[NodeID | None, Header()] = None,
132120
) -> Job:
133121
"""
134122
hidden -- if True (default) hides project from UI
135123
"""
136-
project = await webserver_api.clone_project(
137-
project_id=study_id,
124+
125+
job = await job_service.create_studies_job(
126+
study_id=study_id,
127+
job_inputs=job_inputs,
128+
x_simcore_parent_project_uuid=x_simcore_parent_project_uuid,
129+
x_simcore_parent_node_id=x_simcore_parent_node_id,
138130
hidden=hidden,
139-
parent_project_uuid=x_simcore_parent_project_uuid,
140-
parent_node_id=x_simcore_parent_node_id,
141-
)
142-
job = create_job_from_study(
143-
study_key=study_id, project=project, job_inputs=job_inputs
144131
)
132+
assert job.name == _compose_job_resource_name(study_id, job.id)
145133
job.url = url_for(
146134
"get_study_job",
147135
study_id=study_id,
@@ -153,54 +141,6 @@ async def create_study_job(
153141
study_id=study_id,
154142
job_id=job.id,
155143
)
156-
157-
await webserver_api.patch_project(
158-
project_id=job.id,
159-
patch_params=ProjectPatch(name=job.name),
160-
)
161-
162-
await wb_api_rpc.mark_project_as_job(
163-
product_name=product_name,
164-
user_id=user_id,
165-
project_uuid=job.id,
166-
job_parent_resource_name=job.runner_name,
167-
storage_assets_deleted=False,
168-
)
169-
170-
project_inputs = await webserver_api.get_project_inputs(project_id=project.uuid)
171-
172-
file_param_nodes = {}
173-
for node_id, node in project.workbench.items():
174-
if (
175-
node.key == file_picker.META.key
176-
and node.outputs is not None
177-
and len(node.outputs) == 0
178-
):
179-
file_param_nodes[node.label] = node_id
180-
181-
file_inputs: dict[InputID, InputTypes] = {}
182-
183-
(
184-
new_project_inputs,
185-
new_project_file_inputs,
186-
) = get_project_and_file_inputs_from_job_inputs(
187-
project_inputs, file_inputs, job_inputs
188-
)
189-
190-
for node_label, file_link in new_project_file_inputs.items():
191-
await webserver_api.update_node_outputs(
192-
project_id=project.uuid,
193-
node_id=UUID(file_param_nodes[node_label]),
194-
new_node_outputs=NodeOutputs(outputs={"outFile": file_link}),
195-
)
196-
197-
if len(new_project_inputs) > 0:
198-
await webserver_api.update_project_inputs(
199-
project_id=project.uuid, new_inputs=new_project_inputs
200-
)
201-
202-
assert job.name == _compose_job_resource_name(study_id, job.id)
203-
204144
return job
205145

206146

0 commit comments

Comments
 (0)