Skip to content

Commit b2e6286

Browse files
committed
drafts rpc
1 parent 5d0720f commit b2e6286

File tree

4 files changed

+149
-0
lines changed

4 files changed

+149
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from datetime import datetime
2+
from typing import Annotated, TypeAlias
3+
4+
from models_library.projects import NodesDict, ProjectID
5+
from models_library.rpc_pagination import PageRpc
6+
from pydantic import BaseModel, ConfigDict, Field
7+
8+
9+
class ProjectRpcGet(BaseModel):
10+
uuid: Annotated[
11+
ProjectID,
12+
Field(description="project unique identifier"),
13+
]
14+
name: Annotated[
15+
str,
16+
Field(description="project display name"),
17+
]
18+
description: str
19+
20+
# timestamps
21+
creation_date: datetime
22+
last_change_date: datetime
23+
24+
workbench: Annotated[NodesDict, Field(description="Project's pipeline")]
25+
26+
model_config = ConfigDict(
27+
extra="forbid",
28+
populate_by_name=True,
29+
)
30+
31+
32+
PageRpcProjectRpcGet: TypeAlias = PageRpc[
33+
# WARNING: keep this definition in models_library and not in the RPC interface
34+
# otherwise the metaclass PageRpc[*] will create *different* classes in server/client side
35+
# and will fail to serialize/deserialize these parameters when transmitted/received
36+
ProjectRpcGet
37+
]

packages/service-library/src/servicelib/rabbitmq/rpc_interfaces/webserver/projects.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
from models_library.products import ProductName
55
from models_library.projects import ProjectID
66
from models_library.rabbitmq_basic_types import RPCMethodName
7+
from models_library.rest_pagination import PageOffsetInt
8+
from models_library.rpc.webserver.projects import PageRpcProjectRpcGet
9+
from models_library.rpc_pagination import (
10+
DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
11+
PageLimitInt,
12+
)
713
from models_library.users import UserID
814
from pydantic import TypeAdapter, validate_call
915
from servicelib.logging_utils import log_decorator
@@ -32,3 +38,29 @@ async def mark_project_as_job(
3238
job_parent_resource_name=job_parent_resource_name,
3339
)
3440
assert result is None
41+
42+
43+
@log_decorator(_logger, level=logging.DEBUG)
44+
@validate_call(config={"arbitrary_types_allowed": True})
45+
async def list_my_projects_marked_as_jobs(
46+
rpc_client: RabbitMQRPCClient,
47+
*,
48+
product_name: ProductName,
49+
user_id: UserID,
50+
# pagination
51+
offset: PageOffsetInt = 0,
52+
limit: PageLimitInt = DEFAULT_NUMBER_OF_ITEMS_PER_PAGE,
53+
# filters
54+
job_parent_resource_name_filter: str | None = None,
55+
) -> PageRpcProjectRpcGet:
56+
result = await rpc_client.request(
57+
WEBSERVER_RPC_NAMESPACE,
58+
TypeAdapter(RPCMethodName).validate_python("list_my_projects_marked_as_jobs"),
59+
product_name=product_name,
60+
user_id=user_id,
61+
offset=offset,
62+
limit=limit,
63+
job_parent_resource_name_filter=job_parent_resource_name_filter,
64+
)
65+
assert TypeAdapter(PageRpcProjectRpcGet).validate_python(result) # nosec
66+
return result

services/web/server/src/simcore_service_webserver/projects/_controller/projects_rpc.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from models_library.api_schemas_webserver import WEBSERVER_RPC_NAMESPACE
33
from models_library.products import ProductName
44
from models_library.projects import ProjectID
5+
from models_library.rest_pagination import PageLimitInt, PageOffsetInt
6+
from models_library.rpc.webserver.projects import PageRpcProjectRpcGet, ProjectRpcGet
57
from models_library.users import UserID
68
from pydantic import ValidationError, validate_call
79
from servicelib.rabbitmq import RPCRouter
@@ -50,6 +52,51 @@ async def mark_project_as_job(
5052
raise ProjectNotFoundRpcError.from_domain_error(err) from err
5153

5254

55+
@router.expose(reraise_if_error_type=(ValidationError,))
56+
@validate_call(config={"arbitrary_types_allowed": True})
57+
async def list_my_projects_marked_as_jobs(
58+
app: web.Application,
59+
*,
60+
product_name: ProductName,
61+
user_id: UserID,
62+
# pagination
63+
offset: PageOffsetInt,
64+
limit: PageLimitInt,
65+
# filters
66+
job_parent_resource_name_filter: str | None,
67+
) -> PageRpcProjectRpcGet:
68+
69+
total, projects = await _jobs_service.list_my_projects_marked_as_jobs(
70+
app,
71+
product_name=product_name,
72+
user_id=user_id,
73+
offset=offset,
74+
limit=limit,
75+
job_parent_resource_name_filter=job_parent_resource_name_filter,
76+
)
77+
78+
job_projects = [
79+
ProjectRpcGet(
80+
uuid=project.uuid,
81+
name=project.name,
82+
description=project.description,
83+
creation_date=project.creation_date,
84+
last_change_date=project.last_change_date,
85+
workbench={},
86+
)
87+
for project in projects
88+
]
89+
90+
page: PageRpcProjectRpcGet = PageRpcProjectRpcGet.create(
91+
job_projects,
92+
total=total,
93+
limit=limit,
94+
offset=offset,
95+
)
96+
97+
return page
98+
99+
53100
async def register_rpc_routes_on_startup(app: web.Application):
54101
rpc_server = get_rabbitmq_rpc_server(app)
55102
await rpc_server.register_router(router, WEBSERVER_RPC_NAMESPACE, app)

services/web/server/tests/unit/with_dbs/02/test_projects_rpc.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from common_library.users_enums import UserRole
1313
from models_library.products import ProductName
1414
from models_library.projects import ProjectID
15+
from models_library.rpc.webserver.projects import PageRpcProjectRpcGet, ProjectRpcGet
1516
from pydantic import ValidationError
1617
from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict
1718
from pytest_simcore.helpers.typing_env import EnvVarsDict
@@ -87,6 +88,38 @@ async def test_rpc_client_mark_project_as_job(
8788
)
8889

8990

91+
async def test_rpc_client_list_my_projects_marked_as_jobs(
92+
rpc_client: RabbitMQRPCClient,
93+
product_name: ProductName,
94+
logged_user: UserInfoDict,
95+
user_project: ProjectDict,
96+
):
97+
project_uuid = ProjectID(user_project["uuid"])
98+
user_id = logged_user["id"]
99+
100+
# Mark the project as a job first
101+
await projects_rpc.mark_project_as_job(
102+
rpc_client=rpc_client,
103+
product_name=product_name,
104+
user_id=user_id,
105+
project_uuid=project_uuid,
106+
job_parent_resource_name="solvers/solver123/version/1.2.3",
107+
)
108+
109+
# List projects marked as jobs
110+
page: PageRpcProjectRpcGet = await projects_rpc.list_my_projects_marked_as_jobs(
111+
rpc_client=rpc_client,
112+
product_name=product_name,
113+
user_id=user_id,
114+
job_parent_resource_name_filter="solvers/solver123",
115+
)
116+
117+
assert page.meta.total == 1
118+
assert page.meta.offset == 0
119+
assert isinstance(page.data[0], ProjectRpcGet)
120+
assert page.data[0].uuid == project_uuid
121+
122+
90123
@pytest.fixture
91124
async def other_user(
92125
client: TestClient,

0 commit comments

Comments
 (0)