Skip to content

Commit 3378148

Browse files
committed
move start_solver_job to job_service
1 parent 3520ce4 commit 3378148

File tree

4 files changed

+61
-48
lines changed

4 files changed

+61
-48
lines changed

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

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,27 @@
2222
from models_library.users import UserID
2323
from pydantic import HttpUrl
2424
from servicelib.logging_utils import log_context
25+
from simcore_service_api_server.api.routes.solvers_jobs import compose_job_resource_name
2526

2627
from ._service_solvers import (
2728
SolverService,
2829
)
30+
from .exceptions.backend_errors import JobAssetsMissingError, ProjectAlreadyStartedError
2931
from .exceptions.custom_errors import SolverServiceListJobsFiltersError
3032
from .models.api_resources import RelativeResourceName
3133
from .models.basic_types import NameValueTuple, VersionStr
32-
from .models.schemas.jobs import Job, JobID, JobInputs, compose_resource_name
34+
from .models.schemas.jobs import (
35+
Job,
36+
JobID,
37+
JobInputs,
38+
JobPricingSpecification,
39+
compose_resource_name,
40+
)
3341
from .models.schemas.programs import Program
3442
from .models.schemas.solvers import Solver, SolverKeyId
3543
from .models.schemas.studies import StudyID
3644
from .services_http.director_v2 import DirectorV2Api
45+
from .services_http.jobs import start_project
3746
from .services_http.solver_job_models_converters import (
3847
JobStatus,
3948
create_job_from_project,
@@ -317,3 +326,39 @@ async def inspect_solver_job(
317326
)
318327
job_status: JobStatus = create_jobstatus_from_task(task)
319328
return job_status
329+
330+
async def start_solver_job(
331+
self,
332+
*,
333+
solver_key: SolverKeyId,
334+
version: VersionStr,
335+
job_id: JobID,
336+
pricing_spec: JobPricingSpecification | None,
337+
):
338+
job_name = compose_job_resource_name(solver_key, version, job_id)
339+
_logger.debug("Start Job '%s'", job_name)
340+
job_parent_resource_name = Solver.compose_resource_name(solver_key, version)
341+
job = await self.get_job(
342+
job_id=job_id, job_parent_resource_name=job_parent_resource_name
343+
)
344+
if job.storage_assets_deleted:
345+
raise JobAssetsMissingError(job_id=job_id)
346+
try:
347+
await start_project(
348+
pricing_spec=pricing_spec,
349+
job_id=job_id,
350+
expected_job_name=job_name,
351+
webserver_api=self._web_rest_client,
352+
)
353+
except ProjectAlreadyStartedError:
354+
job_status = await self.inspect_solver_job(
355+
solver_key=solver_key,
356+
version=version,
357+
job_id=job_id,
358+
)
359+
return job_status
360+
return await self.inspect_solver_job(
361+
solver_key=solver_key,
362+
version=version,
363+
job_id=job_id,
364+
)

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

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@
44
from collections.abc import Callable
55
from typing import Annotated, Any
66

7-
from fastapi import APIRouter, Depends, Header, HTTPException, Query, Request, status
8-
from fastapi.encoders import jsonable_encoder
9-
from fastapi.responses import JSONResponse
7+
from fastapi import APIRouter, Depends, Header, Query, Request, status
108
from models_library.clusters import ClusterID
119
from models_library.projects import ProjectID
1210
from models_library.projects_nodes_io import NodeID
1311
from pydantic.types import PositiveInt
1412

1513
from ..._service_jobs import JobService
16-
from ...exceptions.backend_errors import ProjectAlreadyStartedError
1714
from ...exceptions.service_errors_utils import DEFAULT_BACKEND_SERVICE_STATUS_CODES
1815
from ...models.basic_types import VersionStr
1916
from ...models.schemas.errors import ErrorGet
@@ -23,11 +20,12 @@
2320
JobInputs,
2421
JobMetadata,
2522
JobMetadataUpdate,
23+
JobPricingSpecification,
2624
JobStatus,
2725
)
2826
from ...models.schemas.solvers import Solver, SolverKeyId
2927
from ...services_http.director_v2 import DirectorV2Api
30-
from ...services_http.jobs import replace_custom_metadata, start_project, stop_project
28+
from ...services_http.jobs import replace_custom_metadata, stop_project
3129
from ..dependencies.application import get_reverse_url_mapper
3230
from ..dependencies.authentication import get_current_user_id
3331
from ..dependencies.services import get_api_client, get_job_service
@@ -211,49 +209,15 @@ async def start_job(
211209
solver_key: SolverKeyId,
212210
version: VersionStr,
213211
job_id: JobID,
214-
user_id: Annotated[PositiveInt, Depends(get_current_user_id)],
215-
director2_api: Annotated[DirectorV2Api, Depends(get_api_client(DirectorV2Api))],
216-
webserver_api: Annotated[AuthSession, Depends(get_webserver_session)],
217212
job_service: Annotated[JobService, Depends(get_job_service)],
218213
cluster_id: Annotated[ # pylint: disable=unused-argument # noqa: ARG001
219214
ClusterID | None, Query(deprecated=True)
220215
] = None,
221216
):
222-
job_name = compose_job_resource_name(solver_key, version, job_id)
223-
_logger.debug("Start Job '%s'", job_name)
217+
pricing_spec = JobPricingSpecification.create_from_headers(headers=request.headers)
224218

225-
job_parent_resource_name = Solver.compose_resource_name(solver_key, version)
226-
job = await job_service.get_job(
227-
job_id=job_id, job_parent_resource_name=job_parent_resource_name
228-
)
229-
if job.storage_assets_deleted:
230-
raise HTTPException(
231-
status_code=status.HTTP_409_CONFLICT,
232-
detail=f"Assets for job job_id={job_id} are missing",
233-
)
234-
235-
try:
236-
await start_project(
237-
request=request,
238-
job_id=job_id,
239-
expected_job_name=job_name,
240-
webserver_api=webserver_api,
241-
)
242-
except ProjectAlreadyStartedError:
243-
job_status = await inspect_job(
244-
solver_key=solver_key,
245-
version=version,
246-
job_id=job_id,
247-
job_service=job_service,
248-
)
249-
return JSONResponse(
250-
status_code=status.HTTP_200_OK, content=jsonable_encoder(job_status)
251-
)
252-
return await inspect_job(
253-
solver_key=solver_key,
254-
version=version,
255-
job_id=job_id,
256-
job_service=job_service,
219+
return await job_service.start_solver_job(
220+
solver_key=solver_key, version=version, job_id=job_id, pricing_spec=pricing_spec
257221
)
258222

259223

services/api-server/src/simcore_service_api_server/exceptions/backend_errors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,8 @@ class CanNotCheckoutServiceIsNotRunningError(BaseBackEndError):
140140
class LicensedItemCheckoutNotFoundError(BaseBackEndError):
141141
msg_template = "Licensed item checkout {licensed_item_checkout_id} not found."
142142
status_code = status.HTTP_404_NOT_FOUND
143+
144+
145+
class JobAssetsMissingError(BaseBackEndError):
146+
msg_template = "Job assets missing for job {job_id}"
147+
status_code = status.HTTP_409_CONFLICT

services/api-server/src/simcore_service_api_server/services_http/jobs.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
from typing import Annotated
33
from uuid import UUID
44

5-
from fastapi import Depends, HTTPException, Request, status
5+
from fastapi import Depends, HTTPException, status
66
from models_library.api_schemas_webserver.projects import ProjectGet
77
from pydantic import HttpUrl, PositiveInt
88
from servicelib.logging_utils import log_context
99

1010
from ..api.dependencies.authentication import get_current_user_id
1111
from ..api.dependencies.services import get_api_client
12-
from ..api.dependencies.webserver_http import get_webserver_session
1312
from ..models.schemas.jobs import (
1413
JobID,
1514
JobMetadata,
@@ -36,12 +35,12 @@ def raise_if_job_not_associated_with_solver(
3635

3736
async def start_project(
3837
*,
39-
request: Request,
4038
job_id: JobID,
4139
expected_job_name: str,
42-
webserver_api: Annotated[AuthSession, Depends(get_webserver_session)],
40+
pricing_spec: JobPricingSpecification | None,
41+
webserver_api: AuthSession,
4342
) -> None:
44-
if pricing_spec := JobPricingSpecification.create_from_headers(request.headers):
43+
if pricing_spec is not None:
4544
with log_context(_logger, logging.DEBUG, "Set pricing plan and unit"):
4645
project: ProjectGet = await webserver_api.get_project(project_id=job_id)
4746
raise_if_job_not_associated_with_solver(expected_job_name, project)

0 commit comments

Comments
 (0)