Skip to content

Commit 8031bad

Browse files
authored
Merge branch 'master' into enh/state-through-store
2 parents ed8bba0 + 2bdc986 commit 8031bad

File tree

111 files changed

+1324
-792
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+1324
-792
lines changed

api/specs/web-server/_computations.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
from models_library.api_schemas_webserver.computations import (
77
ComputationCollectionRunListQueryParams,
88
ComputationCollectionRunPathParams,
9+
ComputationCollectionRunRestGet,
910
ComputationCollectionRunTaskListQueryParams,
11+
ComputationCollectionRunTaskRestGet,
1012
ComputationGet,
1113
ComputationPathParams,
1214
ComputationRunIterationsLatestListQueryParams,
@@ -102,7 +104,7 @@ async def list_computations_latest_iteration_tasks(
102104

103105
@router.get(
104106
"/computation-collection-runs",
105-
response_model=Page[ComputationTaskRestGet],
107+
response_model=Page[ComputationCollectionRunRestGet],
106108
)
107109
async def list_computation_collection_runs(
108110
_query: Annotated[as_query(ComputationCollectionRunListQueryParams), Depends()],
@@ -111,7 +113,7 @@ async def list_computation_collection_runs(
111113

112114
@router.get(
113115
"/computation-collection-runs/{collection_run_id}/tasks",
114-
response_model=Page[ComputationTaskRestGet],
116+
response_model=Page[ComputationCollectionRunTaskRestGet],
115117
)
116118
async def list_computation_collection_run_tasks(
117119
_query: Annotated[as_query(ComputationCollectionRunTaskListQueryParams), Depends()],

api/specs/web-server/_users.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,22 @@
1414
MyProfilePatch,
1515
MyTokenCreate,
1616
MyTokenGet,
17+
TokenPathParams,
1718
UserGet,
1819
UsersSearch,
1920
)
2021
from models_library.api_schemas_webserver.users_preferences import PatchRequestBody
2122
from models_library.generics import Envelope
2223
from models_library.user_preferences import PreferenceIdentifier
2324
from simcore_service_webserver._meta import API_VTAG
24-
from simcore_service_webserver.users._notifications import (
25+
from simcore_service_webserver.user_notifications._controller.rest.user_notification_rest import (
26+
NotificationPathParams,
27+
)
28+
from simcore_service_webserver.user_notifications._models import (
2529
UserNotification,
2630
UserNotificationCreate,
2731
UserNotificationPatch,
2832
)
29-
from simcore_service_webserver.users._notifications_rest import _NotificationPathParams
30-
from simcore_service_webserver.users._tokens_rest import _TokenPathParams
3133

3234
router = APIRouter(prefix=f"/{API_VTAG}", tags=["users"])
3335

@@ -76,15 +78,15 @@ async def create_token(_body: MyTokenCreate): ...
7678
response_model=Envelope[MyTokenGet],
7779
)
7880
async def get_token(
79-
_path: Annotated[_TokenPathParams, Depends()],
81+
_path: Annotated[TokenPathParams, Depends()],
8082
): ...
8183

8284

8385
@router.delete(
8486
"/me/tokens/{service}",
8587
status_code=status.HTTP_204_NO_CONTENT,
8688
)
87-
async def delete_token(_path: Annotated[_TokenPathParams, Depends()]): ...
89+
async def delete_token(_path: Annotated[TokenPathParams, Depends()]): ...
8890

8991

9092
@router.get(
@@ -108,7 +110,7 @@ async def create_user_notification(
108110
status_code=status.HTTP_204_NO_CONTENT,
109111
)
110112
async def mark_notification_as_read(
111-
_path: Annotated[_NotificationPathParams, Depends()],
113+
_path: Annotated[NotificationPathParams, Depends()],
112114
_body: UserNotificationPatch,
113115
): ...
114116

packages/models-library/src/models_library/api_schemas_webserver/users.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from models_library.rest_filters import Filters
1212
from models_library.rest_pagination import PageQueryParameters
1313
from pydantic import (
14+
BaseModel,
1415
ConfigDict,
1516
EmailStr,
1617
Field,
@@ -334,6 +335,10 @@ def _consistency_check(cls, v, info: ValidationInfo):
334335
#
335336

336337

338+
class TokenPathParams(BaseModel):
339+
service: str
340+
341+
337342
class MyTokenCreate(InputSchemaWithoutCamelCase):
338343
service: Annotated[
339344
IDStr,

packages/service-library/src/servicelib/aiohttp/observer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from collections.abc import Callable
99

1010
from aiohttp import web
11+
from servicelib.aiohttp.application_setup import ensure_single_setup
1112

1213
from ..utils import logged_gather
1314

@@ -17,10 +18,10 @@
1718
_APP_OBSERVER_EVENTS_REGISTRY_KEY = "{__name__}.event_registry"
1819

1920

20-
class ObserverRegistryNotFoundError(RuntimeError):
21-
...
21+
class ObserverRegistryNotFoundError(RuntimeError): ...
2222

2323

24+
@ensure_single_setup(__name__, logger=log)
2425
def setup_observer_registry(app: web.Application):
2526
# only once
2627
app.setdefault(_APP_OBSERVER_EVENTS_REGISTRY_KEY, defaultdict(list))

services/director-v2/src/simcore_service_director_v2/api/rpc/_computations.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ async def list_computation_collection_runs_page(
114114
collection_run_ids = await comp_runs_repo.list_all_collection_run_ids_for_user_currently_running_computations(
115115
product_name=product_name, user_id=user_id
116116
)
117+
if collection_run_ids == []:
118+
return ComputationCollectionRunRpcGetPage(items=[], total=0)
117119

118120
total, comp_runs_output = await comp_runs_repo.list_group_by_collection_run_id(
119121
product_name=product_name,

services/director-v2/src/simcore_service_director_v2/modules/db/repositories/comp_runs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,13 @@ async def list_group_by_collection_run_id(
458458
& (comp_runs.c.metadata["product_name"].astext == product_name)
459459
)
460460

461-
if project_ids_or_none:
461+
if project_ids_or_none is not None:
462462
base_select_query = base_select_query.where(
463463
comp_runs.c.project_uuid.in_(
464464
[f"{project_id}" for project_id in project_ids_or_none]
465465
)
466466
)
467-
if collection_run_ids_or_none:
467+
if collection_run_ids_or_none is not None:
468468
base_select_query = base_select_query.where(
469469
comp_runs.c.collection_run_id.in_(
470470
[

services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_rpc_computations.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,82 @@ async def test_rpc_list_computation_collection_runs_page_and_collection_run_task
341341
assert len(output.items) == 1
342342
assert isinstance(output, ComputationCollectionRunRpcGetPage)
343343
assert len(output.items[0].project_ids) == 2
344+
345+
346+
async def test_rpc_list_computation_collection_runs_empty_ids_when_user_has_already_run_history(
347+
fake_workbench_without_outputs: dict[str, Any], # <-- Has 4 nodes
348+
fake_workbench_adjacency: dict[str, Any],
349+
create_registered_user: Callable[..., dict[str, Any]],
350+
create_project: Callable[..., Awaitable[ProjectAtDB]],
351+
create_pipeline: Callable[..., Awaitable[CompPipelineAtDB]],
352+
create_tasks_from_project: Callable[..., Awaitable[list[CompTaskAtDB]]],
353+
create_comp_run_snapshot_tasks: Callable[
354+
..., Awaitable[list[CompRunSnapshotTaskDBGet]]
355+
],
356+
create_comp_run: Callable[..., Awaitable[CompRunsAtDB]],
357+
rpc_client: RabbitMQRPCClient,
358+
faker: Faker,
359+
with_product: dict[str, Any],
360+
):
361+
user = create_registered_user()
362+
proj = await create_project(user, workbench=fake_workbench_without_outputs)
363+
364+
await create_pipeline(
365+
project_id=f"{proj.uuid}",
366+
dag_adjacency_list=fake_workbench_adjacency,
367+
)
368+
await create_tasks_from_project(
369+
user=user, project=proj, state=RunningState.SUCCESS, progress=None
370+
)
371+
run = await create_comp_run(
372+
user=user,
373+
project=proj,
374+
result=RunningState.SUCCESS,
375+
started=datetime.now(tz=UTC) - timedelta(minutes=120),
376+
ended=datetime.now(tz=UTC) - timedelta(minutes=100),
377+
iteration=1,
378+
dag_adjacency_list=fake_workbench_adjacency,
379+
)
380+
await create_comp_run_snapshot_tasks(
381+
user=user,
382+
project=proj,
383+
run_id=run.run_id,
384+
)
385+
386+
output = await rpc_computations.list_computation_collection_runs_page(
387+
rpc_client, product_name="osparc", user_id=user["id"], project_ids=None
388+
)
389+
assert output.total == 1
390+
assert len(output.items) == 1
391+
assert isinstance(output, ComputationCollectionRunRpcGetPage)
392+
393+
# Test filtering only running collection runs
394+
output = await rpc_computations.list_computation_collection_runs_page(
395+
rpc_client,
396+
product_name="osparc",
397+
user_id=user["id"],
398+
project_ids=None,
399+
filter_only_running=True, # <-- This is the tested filter
400+
)
401+
assert output.total == 0
402+
assert len(output.items) == 0
403+
404+
405+
async def test_rpc_list_computation_collection_runs_empty_ids_when_user_do_not_have_run_history(
406+
create_registered_user: Callable[..., dict[str, Any]],
407+
rpc_client: RabbitMQRPCClient,
408+
with_product: dict[str, Any],
409+
):
410+
user = create_registered_user()
411+
412+
# Test with empty collection_run_ids
413+
output = await rpc_computations.list_computation_collection_runs_page(
414+
rpc_client,
415+
product_name="osparc",
416+
user_id=user["id"],
417+
project_ids=None,
418+
filter_only_running=True, # This will result in empty collection_run_ids
419+
)
420+
assert output.total == 0
421+
assert len(output.items) == 0
422+
assert isinstance(output, ComputationCollectionRunRpcGetPage)

0 commit comments

Comments
 (0)