Skip to content

Commit f820e59

Browse files
committed
bugfix: issue webserver wrongly retrieves templates running state, creating log pollution ITISFoundation#2108
1 parent 4248de7 commit f820e59

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

services/web/server/src/simcore_service_webserver/projects/projects_api.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,19 @@ async def get_project_for_user(
8080
db = app[APP_PROJECT_DBAPI]
8181

8282
project: Dict = None
83+
is_template = False
8384
if include_templates:
8485
project = await db.get_template_project(project_uuid)
86+
is_template = bool(project)
8587

8688
if not project:
8789
project = await db.get_user_project(user_id, project_uuid)
8890

8991
# adds state if it is not a template
9092
if include_state:
91-
project["state"] = await get_project_state_for_user(user_id, project_uuid, app)
93+
project["state"] = await get_project_state_for_user(
94+
user_id, project_uuid, is_template, app
95+
)
9296

9397
# TODO: how to handle when database has an invalid project schema???
9498
# Notice that db model does not include a check on project schema.
@@ -310,7 +314,7 @@ async def update_project_node_state(
310314
db = app[APP_PROJECT_DBAPI]
311315
updated_project = await db.update_user_project(project, user_id, project_id)
312316
updated_project["state"] = await get_project_state_for_user(
313-
user_id, project_id, app
317+
user_id=user_id, project_uuid=project_id, is_template=False, app=app
314318
)
315319
return updated_project
316320

@@ -333,7 +337,7 @@ async def update_project_node_progress(
333337
db = app[APP_PROJECT_DBAPI]
334338
updated_project = await db.update_user_project(project, user_id, project_id)
335339
updated_project["state"] = await get_project_state_for_user(
336-
user_id, project_id, app
340+
user_id=user_id, project_uuid=project_id, is_template=False, app=app
337341
)
338342
return updated_project
339343

@@ -379,7 +383,7 @@ async def update_project_node_outputs(
379383
db = app[APP_PROJECT_DBAPI]
380384
updated_project = await db.update_user_project(project, user_id, project_id)
381385
updated_project["state"] = await get_project_state_for_user(
382-
user_id, project_id, app
386+
user_id=user_id, project_uuid=project_id, is_template=False, app=app
383387
)
384388
return updated_project, changed_keys
385389

@@ -499,13 +503,19 @@ async def _get_project_lock_state(
499503

500504

501505
async def _get_project_running_state(
502-
user_id: PositiveInt, project_uuid: str, app: web.Application
506+
user_id: PositiveInt, project_uuid: str, is_template: bool, app: web.Application
503507
) -> ProjectRunningState:
504-
pipeline_state: RunningState = await get_pipeline_state(app, user_id, project_uuid)
508+
pipeline_state: RunningState = (
509+
RunningState.UNKNOWN
510+
if is_template
511+
else await get_pipeline_state(app, user_id, project_uuid)
512+
)
505513
return ProjectRunningState(value=pipeline_state)
506514

507515

508-
async def get_project_state_for_user(user_id, project_uuid, app) -> Dict:
516+
async def get_project_state_for_user(
517+
user_id: int, project_uuid: str, is_template: bool, app
518+
) -> Dict:
509519
"""
510520
Returns state of a project with respect to a given user
511521
E.g.
@@ -517,7 +527,9 @@ async def get_project_state_for_user(user_id, project_uuid, app) -> Dict:
517527
might require a mock for this function to work properly
518528
"""
519529
lock_state = await _get_project_lock_state(user_id, project_uuid, app)
520-
running_state = await _get_project_running_state(user_id, project_uuid, app)
530+
running_state = await _get_project_running_state(
531+
user_id, project_uuid, is_template, app
532+
)
521533
return ProjectState(
522534
locked=lock_state,
523535
state=running_state,

services/web/server/src/simcore_service_webserver/projects/projects_handlers.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""
44
import json
55
import logging
6-
from typing import Dict, List, Optional, Set
6+
from typing import Any, Dict, List, Optional, Set
77

88
import aioredlock
99
from aiohttp import web
@@ -100,7 +100,10 @@ async def create_projects(request: web.Request):
100100

101101
# Appends state
102102
project["state"] = await projects_api.get_project_state_for_user(
103-
user_id, project["uuid"], request.app
103+
user_id=user_id,
104+
project_uuid=project["uuid"],
105+
is_template=as_template is not None,
106+
app=request.app,
104107
)
105108

106109
except ValidationError as exc:
@@ -125,12 +128,30 @@ async def list_projects(request: web.Request):
125128
db = request.config_dict[APP_PROJECT_DBAPI]
126129

127130
# TODO: improve dbapi to list project
131+
async def add_prj_state(project: Dict[str, Any], is_template: bool) -> None:
132+
project["state"] = await projects_api.get_project_state_for_user(
133+
user_id=user_id,
134+
project_uuid=project["uuid"],
135+
is_template=is_template,
136+
app=request.app,
137+
)
138+
128139
projects_list = []
129140
if ptype in ("template", "all"):
130-
projects_list += await db.load_template_projects(user_id=user_id)
141+
template_projects = await db.load_template_projects(user_id=user_id)
142+
await logged_gather(
143+
*[add_prj_state(prj, is_template=True) for prj in template_projects],
144+
reraise=True,
145+
)
146+
projects_list += template_projects
131147

132148
if ptype in ("user", "all"): # standard only (notice that templates will only)
133-
projects_list += await db.load_user_projects(user_id=user_id)
149+
user_projects = await db.load_user_projects(user_id=user_id)
150+
await logged_gather(
151+
*[add_prj_state(prj, is_template=False) for prj in user_projects],
152+
reraise=True,
153+
)
154+
projects_list += user_projects
134155

135156
start = int(request.query.get("start", 0))
136157
count = int(request.query.get("count", len(projects_list)))
@@ -144,11 +165,8 @@ async def list_projects(request: web.Request):
144165
)
145166

146167
# validate response
147-
async def validate_project(prj: Dict) -> Optional[Dict]:
168+
async def validate_project(prj: Dict[str, Any]) -> Dict[str, Any]:
148169
try:
149-
prj["state"] = await projects_api.get_project_state_for_user(
150-
user_id, project_uuid=prj["uuid"], app=request.app
151-
)
152170
projects_api.validate_project(request.app, prj)
153171
if await project_uses_available_services(prj, user_available_services):
154172
return prj
@@ -259,7 +277,10 @@ async def replace_project(request: web.Request):
259277
await director_v2.create_or_update_pipeline(request.app, user_id, project_uuid)
260278
# Appends state
261279
new_project["state"] = await projects_api.get_project_state_for_user(
262-
user_id, project_uuid, request.app
280+
user_id=user_id,
281+
project_uuid=project_uuid,
282+
is_template=False,
283+
app=request.app,
263284
)
264285

265286
except ValidationError as exc:
@@ -369,7 +390,10 @@ async def try_add_project() -> Optional[Set[int]]:
369390

370391
# notify users that project is now locked
371392
project["state"] = await projects_api.get_project_state_for_user(
372-
user_id, project_uuid, request.app
393+
user_id=user_id,
394+
project_uuid=project_uuid,
395+
is_template=False,
396+
app=request.app,
373397
)
374398

375399
await projects_api.notify_project_state_update(request.app, project)
@@ -417,7 +441,10 @@ async def _close_project_task() -> None:
417441
await rt.remove("project_id")
418442
# ensure we notify the user whatever happens, the GC should take care of dangling services in case of issue
419443
project["state"] = await projects_api.get_project_state_for_user(
420-
user_id, project_uuid, request.app
444+
user_id=user_id,
445+
project_uuid=project_uuid,
446+
is_template=False,
447+
app=request.app,
421448
)
422449
await projects_api.notify_project_state_update(request.app, project)
423450

0 commit comments

Comments
 (0)