Skip to content

Commit c620103

Browse files
progress
1 parent 994ee8f commit c620103

File tree

5 files changed

+89
-53
lines changed

5 files changed

+89
-53
lines changed

api/specs/web-server/_storage.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,15 @@ async def export_data(data_export: DataExportPost, location_id: LocationID):
210210
response_model=Envelope[StorageAsyncJobStatus],
211211
name="get_async_job_status",
212212
)
213-
async def get_async_job_status(storage_async_job_get: StorageAsyncJobGet, job_id: UUID):
213+
async def get_async_job_status(job_id: UUID):
214214
"""Get async job status"""
215215

216216

217217
@router.post(
218218
"/storage/async-jobs/{job_id}:abort",
219219
name="abort_async_job",
220220
)
221-
async def abort_async_job(storage_async_job_get: StorageAsyncJobGet, job_id: UUID):
221+
async def abort_async_job(job_id: UUID):
222222
"""aborts execution of an async job"""
223223

224224

@@ -227,7 +227,7 @@ async def abort_async_job(storage_async_job_get: StorageAsyncJobGet, job_id: UUI
227227
response_model=Envelope[StorageAsyncJobResult],
228228
name="get_async_job_result",
229229
)
230-
async def get_async_job_result(storage_async_job_get: StorageAsyncJobGet, job_id: UUID):
230+
async def get_async_job_result(job_id: UUID):
231231
"""Get the result of the async job"""
232232

233233

services/storage/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ openapi.json: .env-ignore
1515
@set -o allexport; \
1616
source $<; \
1717
set +o allexport; \
18-
python3 -c "import json; from $(APP_PACKAGE_NAME).main import *; print( json.dumps(the_app.openapi(), indent=2) )" > $@
18+
python3 -c "import json; from $(APP_PACKAGE_NAME).main import *; print( json.dumps(app.openapi(), indent=2) )" > $@
1919

2020
# validates OAS file: $@
2121
$(call validate_openapi_specs,$@)

services/storage/tests/unit/test_db_data_export.py

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from models_library.api_schemas_storage.data_export_async_jobs import (
1919
DataExportTaskStartInput,
2020
)
21+
from models_library.progress_bar import ProgressReport
2122
from models_library.projects_nodes_io import NodeID, SimcoreS3FileID
2223
from models_library.users import UserID
2324
from pydantic import ByteSize, TypeAdapter
@@ -28,9 +29,11 @@
2829
from servicelib.rabbitmq import RabbitMQRPCClient
2930
from servicelib.rabbitmq.rpc_interfaces.async_jobs import async_jobs
3031
from settings_library.rabbit import RabbitSettings
31-
from simcore_service_storage.api.rpc._async_jobs import AsyncJobNameData
32+
from simcore_service_storage.api.rpc._async_jobs import AsyncJobNameData, TaskStatus
3233
from simcore_service_storage.api.rpc._data_export import AccessRightError
3334
from simcore_service_storage.core.settings import ApplicationSettings
35+
from simcore_service_storage.modules.celery.client import TaskUUID
36+
from simcore_service_storage.modules.celery.models import TaskState
3437

3538
pytest_plugins = [
3639
"pytest_simcore.rabbit_service",
@@ -42,13 +45,47 @@
4245
"postgres",
4346
]
4447

48+
_faker = Faker()
49+
4550

4651
@pytest.fixture
4752
async def mock_rabbit_setup(mocker: MockerFixture):
4853
# fixture to avoid mocking the rabbit
4954
pass
5055

5156

57+
class _MockCeleryClient:
58+
async def send_task(self, *args, **kwargs) -> TaskUUID:
59+
return _faker.uuid4()
60+
61+
async def get_task_status(self, *args, **kwargs) -> TaskStatus:
62+
return TaskStatus(
63+
task_uuid=_faker.uuid4(),
64+
task_state=TaskState.RUNNING,
65+
progress_report=ProgressReport(actual_value=42.0),
66+
)
67+
68+
async def get_result(self, *args, **kwargs) -> Any:
69+
return {}
70+
71+
async def get_task_uuids(self, *args, **kwargs) -> set[TaskUUID]:
72+
return {_faker.uuid4()}
73+
74+
75+
@pytest.fixture
76+
async def mock_celery_client(mocker: MockerFixture) -> MockerFixture:
77+
_celery_client = _MockCeleryClient()
78+
mocker.patch(
79+
"simcore_service_storage.api.rpc._async_jobs.get_celery_client",
80+
return_value=_celery_client,
81+
)
82+
mocker.patch(
83+
"simcore_service_storage.api.rpc._data_export.get_celery_client",
84+
return_value=_celery_client,
85+
)
86+
return mocker
87+
88+
5289
@pytest.fixture
5390
async def app_environment(
5491
app_environment: EnvVarsDict,
@@ -110,6 +147,7 @@ class UserWithFile(NamedTuple):
110147
)
111148
async def test_start_data_export_success(
112149
rpc_client: RabbitMQRPCClient,
150+
mock_celery_client: MockerFixture,
113151
with_random_project_with_files: tuple[
114152
dict[str, Any],
115153
dict[NodeID, dict[SimcoreS3FileID, FileIDDict]],
@@ -150,7 +188,10 @@ async def test_start_data_export_success(
150188

151189

152190
async def test_start_data_export_fail(
153-
rpc_client: RabbitMQRPCClient, user_id: UserID, faker: Faker
191+
rpc_client: RabbitMQRPCClient,
192+
mock_celery_client: MockerFixture,
193+
user_id: UserID,
194+
faker: Faker,
154195
):
155196

156197
with pytest.raises(AccessRightError):
@@ -168,53 +209,65 @@ async def test_start_data_export_fail(
168209
)
169210

170211

171-
async def test_abort_data_export(rpc_client: RabbitMQRPCClient, faker: Faker):
172-
_job_id = AsyncJobId(faker.uuid4())
212+
async def test_abort_data_export(
213+
rpc_client: RabbitMQRPCClient,
214+
mock_celery_client: MockerFixture,
215+
):
216+
_job_id = AsyncJobId(_faker.uuid4())
173217
result = await async_jobs.abort(
174218
rpc_client,
175219
rpc_namespace=STORAGE_RPC_NAMESPACE,
176220
job_id_data=AsyncJobNameData(
177-
user_id=faker.pyint(min_value=1, max_value=100), product_name="osparc"
221+
user_id=_faker.pyint(min_value=1, max_value=100), product_name="osparc"
178222
),
179223
job_id=_job_id,
180224
)
181225
assert isinstance(result, AsyncJobAbort)
182226
assert result.job_id == _job_id
183227

184228

185-
async def test_get_data_export_status(rpc_client: RabbitMQRPCClient, faker: Faker):
186-
_job_id = AsyncJobId(faker.uuid4())
229+
async def test_get_data_export_status(
230+
rpc_client: RabbitMQRPCClient,
231+
mock_celery_client: MockerFixture,
232+
):
233+
_job_id = AsyncJobId(_faker.uuid4())
187234
result = await async_jobs.get_status(
188235
rpc_client,
189236
rpc_namespace=STORAGE_RPC_NAMESPACE,
190237
job_id=_job_id,
191238
job_id_data=AsyncJobNameData(
192-
user_id=faker.pyint(min_value=1, max_value=100), product_name="osparc"
239+
user_id=_faker.pyint(min_value=1, max_value=100), product_name="osparc"
193240
),
194241
)
195242
assert isinstance(result, AsyncJobStatus)
196243
assert result.job_id == _job_id
197244

198245

199-
async def test_get_data_export_result(rpc_client: RabbitMQRPCClient, faker: Faker):
200-
_job_id = AsyncJobId(faker.uuid4())
246+
async def test_get_data_export_result(
247+
rpc_client: RabbitMQRPCClient,
248+
mock_celery_client: MockerFixture,
249+
):
250+
_job_id = AsyncJobId(_faker.uuid4())
201251
result = await async_jobs.get_result(
202252
rpc_client,
203253
rpc_namespace=STORAGE_RPC_NAMESPACE,
204254
job_id=_job_id,
205255
job_id_data=AsyncJobNameData(
206-
user_id=faker.pyint(min_value=1, max_value=100), product_name="osparc"
256+
user_id=_faker.pyint(min_value=1, max_value=100), product_name="osparc"
207257
),
208258
)
209259
assert isinstance(result, AsyncJobResult)
210260

211261

212-
async def test_list_jobs(rpc_client: RabbitMQRPCClient, faker: Faker):
262+
async def test_list_jobs(
263+
rpc_client: RabbitMQRPCClient,
264+
mock_celery_client: MockerFixture,
265+
):
213266
result = await async_jobs.list_jobs(
214267
rpc_client,
215268
rpc_namespace=STORAGE_RPC_NAMESPACE,
216269
job_id_data=AsyncJobNameData(
217-
user_id=faker.pyint(min_value=1, max_value=100), product_name="osparc"
270+
user_id=_faker.pyint(min_value=1, max_value=100), product_name="osparc"
218271
),
219272
filter_="",
220273
)

services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6405,12 +6405,6 @@ paths:
64056405
type: string
64066406
format: uuid
64076407
title: Job Id
6408-
requestBody:
6409-
required: true
6410-
content:
6411-
application/json:
6412-
schema:
6413-
$ref: '#/components/schemas/StorageAsyncJobGet'
64146408
responses:
64156409
'200':
64166410
description: Successful Response
@@ -6433,12 +6427,6 @@ paths:
64336427
type: string
64346428
format: uuid
64356429
title: Job Id
6436-
requestBody:
6437-
required: true
6438-
content:
6439-
application/json:
6440-
schema:
6441-
$ref: '#/components/schemas/StorageAsyncJobGet'
64426430
responses:
64436431
'200':
64446432
description: Successful Response
@@ -6460,12 +6448,6 @@ paths:
64606448
type: string
64616449
format: uuid
64626450
title: Job Id
6463-
requestBody:
6464-
required: true
6465-
content:
6466-
application/json:
6467-
schema:
6468-
$ref: '#/components/schemas/StorageAsyncJobGet'
64696451
responses:
64706452
'200':
64716453
description: Successful Response
@@ -14715,23 +14697,11 @@ components:
1471514697
done:
1471614698
type: boolean
1471714699
title: Done
14718-
started:
14719-
type: string
14720-
format: date-time
14721-
title: Started
14722-
stopped:
14723-
anyOf:
14724-
- type: string
14725-
format: date-time
14726-
- type: 'null'
14727-
title: Stopped
1472814700
type: object
1472914701
required:
1473014702
- jobId
1473114703
- progress
1473214704
- done
14733-
- started
14734-
- stopped
1473514705
title: StorageAsyncJobStatus
1473614706
Structure:
1473714707
properties:

services/web/server/src/simcore_service_webserver/storage/_rest.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import urllib.parse
88
from typing import Any, Final, NamedTuple
99
from urllib.parse import quote, unquote
10+
from uuid import UUID
1011

1112
from aiohttp import ClientTimeout, web
1213
from models_library.api_schemas_rpc_async_jobs.async_jobs import AsyncJobNameData
@@ -471,10 +472,14 @@ async def get_async_jobs(request: web.Request) -> web.Response:
471472
@permission_required("storage.files.*")
472473
@handle_data_export_exceptions
473474
async def get_async_job_status(request: web.Request) -> web.Response:
475+
476+
class _PathParams(BaseModel):
477+
job_id: UUID
478+
474479
_req_ctx = RequestContext.model_validate(request)
475480
rabbitmq_rpc_client = get_rabbitmq_rpc_client(request.app)
476481

477-
async_job_get = parse_request_path_parameters_as(StorageAsyncJobGet, request)
482+
async_job_get = parse_request_path_parameters_as(_PathParams, request)
478483
async_job_rpc_status = await get_status(
479484
rabbitmq_rpc_client=rabbitmq_rpc_client,
480485
rpc_namespace=STORAGE_RPC_NAMESPACE,
@@ -497,10 +502,13 @@ async def get_async_job_status(request: web.Request) -> web.Response:
497502
@permission_required("storage.files.*")
498503
@handle_data_export_exceptions
499504
async def abort_async_job(request: web.Request) -> web.Response:
505+
class _PathParams(BaseModel):
506+
job_id: UUID
507+
500508
_req_ctx = RequestContext.model_validate(request)
501509

502510
rabbitmq_rpc_client = get_rabbitmq_rpc_client(request.app)
503-
async_job_get = parse_request_path_parameters_as(StorageAsyncJobGet, request)
511+
async_job_get = parse_request_path_parameters_as(_PathParams, request)
504512
async_job_rpc_abort = await abort(
505513
rabbitmq_rpc_client=rabbitmq_rpc_client,
506514
rpc_namespace=STORAGE_RPC_NAMESPACE,
@@ -510,9 +518,11 @@ async def abort_async_job(request: web.Request) -> web.Response:
510518
),
511519
)
512520
return web.Response(
513-
status=status.HTTP_200_OK
514-
if async_job_rpc_abort.result
515-
else status.HTTP_500_INTERNAL_SERVER_ERROR
521+
status=(
522+
status.HTTP_200_OK
523+
if async_job_rpc_abort.result
524+
else status.HTTP_500_INTERNAL_SERVER_ERROR
525+
)
516526
)
517527

518528

@@ -524,10 +534,13 @@ async def abort_async_job(request: web.Request) -> web.Response:
524534
@permission_required("storage.files.*")
525535
@handle_data_export_exceptions
526536
async def get_async_job_result(request: web.Request) -> web.Response:
537+
class _PathParams(BaseModel):
538+
job_id: UUID
539+
527540
_req_ctx = RequestContext.model_validate(request)
528541

529542
rabbitmq_rpc_client = get_rabbitmq_rpc_client(request.app)
530-
async_job_get = parse_request_path_parameters_as(StorageAsyncJobGet, request)
543+
async_job_get = parse_request_path_parameters_as(_PathParams, request)
531544
async_job_rpc_result = await get_result(
532545
rabbitmq_rpc_client=rabbitmq_rpc_client,
533546
rpc_namespace=STORAGE_RPC_NAMESPACE,

0 commit comments

Comments
 (0)