33from typing import Any
44
55from aiohttp import web
6- from common_library .json_serialization import json_dumps
7- from models_library .api_schemas_directorv2 .computations import ComputationGet
8- from models_library .api_schemas_webserver .computations import ComputationStart
6+ from models_library .api_schemas_directorv2 .computations import (
7+ ComputationGet as _ComputationGetDirectorV2 ,
8+ )
9+ from models_library .api_schemas_webserver .computations import (
10+ ComputationGet ,
11+ ComputationPathParams ,
12+ ComputationStart ,
13+ ComputationStarted ,
14+ )
915from models_library .projects import ProjectID
10- from pydantic import BaseModel , Field , TypeAdapter , ValidationError
16+ from pydantic import TypeAdapter , ValidationError
1117from servicelib .aiohttp import status
18+ from servicelib .aiohttp .requests_validation import (
19+ parse_request_body_as ,
20+ parse_request_path_parameters_as ,
21+ )
1222from servicelib .aiohttp .rest_responses import create_http_error , exception_to_response
1323from servicelib .aiohttp .web_exceptions_extension import get_http_error_class_or_none
1424from servicelib .common_headers import (
4050routes = web .RouteTableDef ()
4151
4252
43- class _ComputationStarted (BaseModel ):
44- pipeline_id : ProjectID = Field (
45- ..., description = "ID for created pipeline (=project identifier)"
46- )
47- ref_ids : list [CommitID ] = Field (
48- default_factory = list , description = "Checkpoints IDs for created pipeline"
49- )
50-
51-
5253@routes .post (f"/{ VTAG } /computations/{{project_id}}:start" , name = "start_computation" )
5354@login_required
5455@permission_required ("services.pipeline.*" )
5556@permission_required ("project.read" )
5657async def start_computation (request : web .Request ) -> web .Response :
5758 # pylint: disable=too-many-statements
5859 try :
60+ simcore_user_agent = request .headers .get (
61+ X_SIMCORE_USER_AGENT , UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE
62+ )
5963 req_ctx = RequestContext .model_validate (request )
60- computations = ComputationsApi (request .app )
61-
62- run_policy = get_project_run_policy (request .app )
63- assert run_policy # nosec
64-
65- project_id = ProjectID (request .match_info ["project_id" ])
64+ path_params = parse_request_path_parameters_as (ComputationPathParams , request )
6665
6766 subgraph : set [str ] = set ()
6867 force_restart : bool = False # NOTE: deprecate this entry
69-
7068 if request .can_read_body :
71- body = await request .json ()
72- assert (
73- TypeAdapter (ComputationStart ).validate_python (body ) is not None
74- ) # nosec
75-
76- subgraph = body .get ("subgraph" , [])
77- force_restart = bool (body .get ("force_restart" , force_restart ))
78-
79- simcore_user_agent = request .headers .get (
80- X_SIMCORE_USER_AGENT , UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE
81- )
69+ body_params = await parse_request_body_as (ComputationStart , request )
70+ subgraph = body_params .subgraph
71+ force_restart = body_params .force_restart
8272
8373 async with get_database_engine (request .app ).acquire () as conn :
8474 group_properties = (
@@ -93,7 +83,7 @@ async def start_computation(request: web.Request) -> web.Response:
9383 request .app ,
9484 product = product ,
9585 user_id = req_ctx .user_id ,
96- project_id = project_id ,
86+ project_id = path_params . project_id ,
9787 product_name = req_ctx .product_name ,
9888 )
9989
@@ -106,16 +96,21 @@ async def start_computation(request: web.Request) -> web.Response:
10696 "wallet_info" : wallet_info ,
10797 }
10898
99+ run_policy = get_project_run_policy (request .app )
100+ assert run_policy # nosec
101+
109102 running_project_ids : list [ProjectID ]
110103 project_vc_commits : list [CommitID ]
111104
112105 (
113106 running_project_ids ,
114107 project_vc_commits ,
115- ) = await run_policy .get_or_create_runnable_projects (request , project_id )
108+ ) = await run_policy .get_or_create_runnable_projects (
109+ request , path_params .project_id
110+ )
116111 _logger .debug (
117112 "Project %s will start %d variants: %s" ,
118- f"{ project_id = } " ,
113+ f"{ path_params . project_id = } " ,
119114 len (running_project_ids ),
120115 f"{ running_project_ids = } " ,
121116 )
@@ -127,6 +122,7 @@ async def start_computation(request: web.Request) -> web.Response:
127122 else True
128123 )
129124
125+ computations = ComputationsApi (request .app )
130126 _started_pipelines_ids : list [str ] = await asyncio .gather (
131127 * [
132128 computations .start (
@@ -141,14 +137,14 @@ async def start_computation(request: web.Request) -> web.Response:
141137 ) # nosec
142138
143139 data : dict [str , Any ] = {
144- "pipeline_id" : project_id ,
140+ "pipeline_id" : path_params . project_id ,
145141 }
146142 # Optional
147143 if project_vc_commits :
148144 data ["ref_ids" ] = project_vc_commits
149145
150146 assert (
151- TypeAdapter (_ComputationStarted ).validate_python (data ) is not None
147+ TypeAdapter (ComputationStarted ).validate_python (data ) is not None
152148 ) # nosec
153149
154150 return envelope_json_response (data , status_cls = web .HTTPCreated )
@@ -221,7 +217,9 @@ async def get_computation(request: web.Request) -> web.Response:
221217 request , project_id
222218 )
223219 _logger .debug ("Project %s will get %d variants" , project_id , len (project_ids ))
224- list_computation_tasks = TypeAdapter (list [ComputationGet ]).validate_python (
220+ list_computation_tasks = TypeAdapter (
221+ list [_ComputationGetDirectorV2 ]
222+ ).validate_python (
225223 await asyncio .gather (
226224 * [
227225 computations .get (project_id = pid , user_id = user_id )
@@ -231,10 +229,13 @@ async def get_computation(request: web.Request) -> web.Response:
231229 )
232230 assert len (list_computation_tasks ) == len (project_ids ) # nosec
233231
234- return web .json_response (
235- data = {"data" : list_computation_tasks [0 ].model_dump (by_alias = True )},
236- dumps = json_dumps ,
232+ return envelope_json_response (
233+ [
234+ ComputationGet .model_construct (** m .model_dump (exclude_unset = True ))
235+ for m in list_computation_tasks
236+ ],
237237 )
238+
238239 except DirectorServiceError as exc :
239240 return create_http_error (
240241 exc ,
0 commit comments