diff --git a/api/specs/web-server/_computations.py b/api/specs/web-server/_computations.py index 4b565b9baa99..6264b578ee85 100644 --- a/api/specs/web-server/_computations.py +++ b/api/specs/web-server/_computations.py @@ -6,7 +6,9 @@ from models_library.api_schemas_webserver.computations import ( ComputationCollectionRunListQueryParams, ComputationCollectionRunPathParams, + ComputationCollectionRunRestGet, ComputationCollectionRunTaskListQueryParams, + ComputationCollectionRunTaskRestGet, ComputationGet, ComputationPathParams, ComputationRunIterationsLatestListQueryParams, @@ -102,7 +104,7 @@ async def list_computations_latest_iteration_tasks( @router.get( "/computation-collection-runs", - response_model=Page[ComputationTaskRestGet], + response_model=Page[ComputationCollectionRunRestGet], ) async def list_computation_collection_runs( _query: Annotated[as_query(ComputationCollectionRunListQueryParams), Depends()], @@ -111,7 +113,7 @@ async def list_computation_collection_runs( @router.get( "/computation-collection-runs/{collection_run_id}/tasks", - response_model=Page[ComputationTaskRestGet], + response_model=Page[ComputationCollectionRunTaskRestGet], ) async def list_computation_collection_run_tasks( _query: Annotated[as_query(ComputationCollectionRunTaskListQueryParams), Depends()], diff --git a/services/director-v2/src/simcore_service_director_v2/api/rpc/_computations.py b/services/director-v2/src/simcore_service_director_v2/api/rpc/_computations.py index d8ad583ece72..25d2a133ec57 100644 --- a/services/director-v2/src/simcore_service_director_v2/api/rpc/_computations.py +++ b/services/director-v2/src/simcore_service_director_v2/api/rpc/_computations.py @@ -114,6 +114,8 @@ async def list_computation_collection_runs_page( collection_run_ids = await comp_runs_repo.list_all_collection_run_ids_for_user_currently_running_computations( product_name=product_name, user_id=user_id ) + if collection_run_ids == []: + return ComputationCollectionRunRpcGetPage(items=[], total=0) total, comp_runs_output = await comp_runs_repo.list_group_by_collection_run_id( product_name=product_name, diff --git a/services/director-v2/src/simcore_service_director_v2/modules/db/repositories/comp_runs.py b/services/director-v2/src/simcore_service_director_v2/modules/db/repositories/comp_runs.py index cbc38c983f31..c6b417f9c7d5 100644 --- a/services/director-v2/src/simcore_service_director_v2/modules/db/repositories/comp_runs.py +++ b/services/director-v2/src/simcore_service_director_v2/modules/db/repositories/comp_runs.py @@ -458,13 +458,13 @@ async def list_group_by_collection_run_id( & (comp_runs.c.metadata["product_name"].astext == product_name) ) - if project_ids_or_none: + if project_ids_or_none is not None: base_select_query = base_select_query.where( comp_runs.c.project_uuid.in_( [f"{project_id}" for project_id in project_ids_or_none] ) ) - if collection_run_ids_or_none: + if collection_run_ids_or_none is not None: base_select_query = base_select_query.where( comp_runs.c.collection_run_id.in_( [ diff --git a/services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_rpc_computations.py b/services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_rpc_computations.py index d9429fcbf866..1e21400bcd92 100644 --- a/services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_rpc_computations.py +++ b/services/director-v2/tests/unit/with_dbs/comp_scheduler/test_api_rpc_computations.py @@ -341,3 +341,82 @@ async def test_rpc_list_computation_collection_runs_page_and_collection_run_task assert len(output.items) == 1 assert isinstance(output, ComputationCollectionRunRpcGetPage) assert len(output.items[0].project_ids) == 2 + + +async def test_rpc_list_computation_collection_runs_empty_ids_when_user_has_already_run_history( + fake_workbench_without_outputs: dict[str, Any], # <-- Has 4 nodes + fake_workbench_adjacency: dict[str, Any], + create_registered_user: Callable[..., dict[str, Any]], + create_project: Callable[..., Awaitable[ProjectAtDB]], + create_pipeline: Callable[..., Awaitable[CompPipelineAtDB]], + create_tasks_from_project: Callable[..., Awaitable[list[CompTaskAtDB]]], + create_comp_run_snapshot_tasks: Callable[ + ..., Awaitable[list[CompRunSnapshotTaskDBGet]] + ], + create_comp_run: Callable[..., Awaitable[CompRunsAtDB]], + rpc_client: RabbitMQRPCClient, + faker: Faker, + with_product: dict[str, Any], +): + user = create_registered_user() + proj = await create_project(user, workbench=fake_workbench_without_outputs) + + await create_pipeline( + project_id=f"{proj.uuid}", + dag_adjacency_list=fake_workbench_adjacency, + ) + await create_tasks_from_project( + user=user, project=proj, state=RunningState.SUCCESS, progress=None + ) + run = await create_comp_run( + user=user, + project=proj, + result=RunningState.SUCCESS, + started=datetime.now(tz=UTC) - timedelta(minutes=120), + ended=datetime.now(tz=UTC) - timedelta(minutes=100), + iteration=1, + dag_adjacency_list=fake_workbench_adjacency, + ) + await create_comp_run_snapshot_tasks( + user=user, + project=proj, + run_id=run.run_id, + ) + + output = await rpc_computations.list_computation_collection_runs_page( + rpc_client, product_name="osparc", user_id=user["id"], project_ids=None + ) + assert output.total == 1 + assert len(output.items) == 1 + assert isinstance(output, ComputationCollectionRunRpcGetPage) + + # Test filtering only running collection runs + output = await rpc_computations.list_computation_collection_runs_page( + rpc_client, + product_name="osparc", + user_id=user["id"], + project_ids=None, + filter_only_running=True, # <-- This is the tested filter + ) + assert output.total == 0 + assert len(output.items) == 0 + + +async def test_rpc_list_computation_collection_runs_empty_ids_when_user_do_not_have_run_history( + create_registered_user: Callable[..., dict[str, Any]], + rpc_client: RabbitMQRPCClient, + with_product: dict[str, Any], +): + user = create_registered_user() + + # Test with empty collection_run_ids + output = await rpc_computations.list_computation_collection_runs_page( + rpc_client, + product_name="osparc", + user_id=user["id"], + project_ids=None, + filter_only_running=True, # This will result in empty collection_run_ids + ) + assert output.total == 0 + assert len(output.items) == 0 + assert isinstance(output, ComputationCollectionRunRpcGetPage) diff --git a/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml b/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml index 60d8dc97b91b..301311621541 100644 --- a/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml +++ b/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml @@ -2820,7 +2820,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Page_ComputationTaskRestGet_' + $ref: '#/components/schemas/Page_ComputationCollectionRunRestGet_' /v0/computation-collection-runs/{collection_run_id}/tasks: get: tags: @@ -2856,7 +2856,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Page_ComputationTaskRestGet_' + $ref: '#/components/schemas/Page_ComputationCollectionRunTaskRestGet_' /v0/projects/{project_id}:xport: post: tags: @@ -9357,6 +9357,108 @@ components: required: - version title: CompatibleService + ComputationCollectionRunRestGet: + properties: + collectionRunId: + type: string + format: uuid + title: Collectionrunid + projectIds: + items: + type: string + type: array + title: Projectids + state: + $ref: '#/components/schemas/RunningState' + info: + type: object + title: Info + submittedAt: + type: string + format: date-time + title: Submittedat + startedAt: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Startedat + endedAt: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Endedat + name: + type: string + title: Name + type: object + required: + - collectionRunId + - projectIds + - state + - info + - submittedAt + - startedAt + - endedAt + - name + title: ComputationCollectionRunRestGet + ComputationCollectionRunTaskRestGet: + properties: + projectUuid: + type: string + format: uuid + title: Projectuuid + nodeId: + type: string + format: uuid + title: Nodeid + state: + $ref: '#/components/schemas/RunningState' + progress: + type: number + title: Progress + image: + type: object + title: Image + startedAt: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Startedat + endedAt: + anyOf: + - type: string + format: date-time + - type: 'null' + title: Endedat + logDownloadLink: + anyOf: + - type: string + - type: 'null' + title: Logdownloadlink + osparcCredits: + anyOf: + - type: string + - type: 'null' + title: Osparccredits + name: + type: string + title: Name + type: object + required: + - projectUuid + - nodeId + - state + - progress + - image + - startedAt + - endedAt + - logDownloadLink + - osparcCredits + - name + title: ComputationCollectionRunTaskRestGet ComputationGet: properties: id: @@ -13762,6 +13864,82 @@ components: - _links - data title: Page[CatalogLatestServiceGet] + Page_ComputationCollectionRunRestGet_: + properties: + items: + items: + $ref: '#/components/schemas/ComputationCollectionRunRestGet' + type: array + title: Items + total: + anyOf: + - type: integer + minimum: 0 + - type: 'null' + title: Total + page: + anyOf: + - type: integer + minimum: 1 + - type: 'null' + title: Page + size: + anyOf: + - type: integer + minimum: 1 + - type: 'null' + title: Size + pages: + anyOf: + - type: integer + minimum: 0 + - type: 'null' + title: Pages + type: object + required: + - items + - total + - page + - size + title: Page[ComputationCollectionRunRestGet] + Page_ComputationCollectionRunTaskRestGet_: + properties: + items: + items: + $ref: '#/components/schemas/ComputationCollectionRunTaskRestGet' + type: array + title: Items + total: + anyOf: + - type: integer + minimum: 0 + - type: 'null' + title: Total + page: + anyOf: + - type: integer + minimum: 1 + - type: 'null' + title: Page + size: + anyOf: + - type: integer + minimum: 1 + - type: 'null' + title: Size + pages: + anyOf: + - type: integer + minimum: 0 + - type: 'null' + title: Pages + type: object + required: + - items + - total + - page + - size + title: Page[ComputationCollectionRunTaskRestGet] Page_ComputationRunRestGet_: properties: items: