Skip to content

Commit f6fbf7c

Browse files
committed
add paginated listing of program release history
1 parent 1385100 commit f6fbf7c

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,38 @@ async def list_latest_programs(
5353

5454
items = [Program.create_from_service(service) for service in page]
5555
return items, page_meta
56+
57+
async def list_program_history(
58+
self,
59+
*,
60+
user_id: int,
61+
program_key: ProgramKeyId,
62+
product_name: str,
63+
offset: NonNegativeInt,
64+
limit: PositiveInt,
65+
) -> tuple[list[Program], PageMetaInfoLimitOffset]:
66+
page, page_meta = await self._catalog_service.list_release_history(
67+
user_id=user_id,
68+
service_key=program_key,
69+
product_name=product_name,
70+
offset=offset,
71+
limit=limit,
72+
)
73+
74+
program_instance = await self._catalog_service.get(
75+
user_id=user_id,
76+
name=program_key,
77+
version=page[-1].version,
78+
product_name=product_name,
79+
)
80+
81+
items = [
82+
Program.create_from_service_release(
83+
service=service,
84+
service_key=program_instance.key,
85+
description=program_instance.description,
86+
name=program_instance.name,
87+
)
88+
for service in page
89+
]
90+
return items, page_meta

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,41 @@ async def list_programs(
6363
)
6464

6565

66+
@router.get(
67+
"/{program_key:path}/releases",
68+
response_model=Page[Program],
69+
)
70+
async def list_program_history(
71+
program_key: ProgramKeyId,
72+
user_id: Annotated[PositiveInt, Depends(get_current_user_id)],
73+
program_service: Annotated[ProgramService, Depends()],
74+
url_for: Annotated[Callable, Depends(get_reverse_url_mapper)],
75+
product_name: Annotated[str, Depends(get_product_name)],
76+
page_params: Annotated[PaginationParams, Depends()],
77+
) -> Page[Program]:
78+
"""Lists the latest of all available programs"""
79+
programs, page_meta = await program_service.list_program_history(
80+
program_key=program_key,
81+
user_id=user_id,
82+
product_name=product_name,
83+
offset=page_params.offset,
84+
limit=page_params.limit,
85+
)
86+
page_params.limit = page_meta.limit
87+
page_params.offset = page_meta.offset
88+
89+
for program in programs:
90+
program.url = url_for(
91+
"get_program_release", program_key=program.id, version=program.version
92+
)
93+
94+
return create_page(
95+
programs,
96+
total=len(programs),
97+
params=page_params,
98+
)
99+
100+
66101
@router.get(
67102
"/{program_key:path}/releases/{version}",
68103
response_model=Program,

services/api-server/tests/unit/test_api_programs.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,24 @@ def _side_effect(
115115
job = Job.model_validate(response.json())
116116

117117

118-
async def test_list_programs(
118+
async def test_list_latest_programs(
119119
auth: httpx.BasicAuth,
120120
client: AsyncClient,
121121
mocked_catalog_rpc_api: dict[str, MockType],
122122
):
123123
# Arrange
124124
response = await client.get(f"/{API_VTAG}/programs", auth=auth)
125125
assert response.status_code == status.HTTP_200_OK
126+
127+
128+
async def test_list_program_history(
129+
auth: httpx.BasicAuth,
130+
client: AsyncClient,
131+
mocked_catalog_rpc_api: dict[str, MockType],
132+
):
133+
program_key = "simcore/services/dynamic/my_program"
134+
# Arrange
135+
response = await client.get(
136+
f"/{API_VTAG}/programs/{program_key}/releases", auth=auth
137+
)
138+
assert response.status_code == status.HTTP_200_OK

0 commit comments

Comments
 (0)