Skip to content

Commit 4e79417

Browse files
committed
cleanup retry statement @pcrespov
1 parent a8b6bec commit 4e79417

File tree

3 files changed

+37
-34
lines changed

3 files changed

+37
-34
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import datetime
33
import io
44
import logging
5-
from typing import IO, Annotated, Any, Final
5+
from typing import IO, Annotated, Any
66
from uuid import UUID
77

88
from fastapi import APIRouter, Body, Depends
@@ -66,8 +66,6 @@
6666
#
6767
#
6868

69-
_AIOHTTP_CLIENT_SESSION_TIMEOUT_SECONDS: Final[float] = 60.0
70-
7169
_FILE_STATUS_CODES: dict[int | str, dict[str, Any]] = {
7270
status.HTTP_404_NOT_FOUND: {
7371
"description": "File not found",

services/api-server/src/simcore_service_api_server/exceptions/backend_errors.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ def named_fields(cls) -> set[str]:
1717
)
1818

1919

20+
class BackendTimeoutError(BaseBackEndError):
21+
msg_template = "Backend request timed out"
22+
status_code = status.HTTP_504_GATEWAY_TIMEOUT
23+
24+
2025
class InvalidInputError(BaseBackEndError):
2126
msg_template = "Invalid input"
2227
status_code = status.HTTP_422_UNPROCESSABLE_ENTITY

services/api-server/src/simcore_service_api_server/services_http/storage.py

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import Final, Literal
88
from uuid import UUID
99

10-
from fastapi import FastAPI, HTTPException, status
10+
from fastapi import FastAPI
1111
from fastapi.encoders import jsonable_encoder
1212
from models_library.api_schemas_storage.storage_schemas import (
1313
ETag,
@@ -29,10 +29,12 @@
2929
from models_library.rest_pagination import PageLimitInt, PageOffsetInt
3030
from pydantic import AnyUrl
3131
from settings_library.tracing import TracingSettings
32+
from simcore_service_api_server.exceptions.backend_errors import BackendTimeoutError
3233
from simcore_service_api_server.models.schemas.files import UserFile
3334
from simcore_service_api_server.models.schemas.jobs import UserFileToProgramJob
3435
from tenacity import (
3536
AsyncRetrying,
37+
TryAgain,
3638
before_sleep_log,
3739
retry_if_exception_type,
3840
stop_after_delay,
@@ -210,36 +212,34 @@ async def complete_file_upload(self, *, user_id: int, file: File) -> ETag:
210212
].model_validate_json(response.text)
211213
assert file_upload_complete_response.data # nosec
212214
state_url = f"{file_upload_complete_response.data.links.state}"
213-
async for attempt in AsyncRetrying(
214-
reraise=False,
215-
wait=wait_fixed(1),
216-
stop=stop_after_delay(_POLL_TIMEOUT),
217-
retry=retry_if_exception_type(ValueError),
218-
before_sleep=before_sleep_log(_logger, logging.DEBUG),
219-
):
220-
with attempt:
221-
resp = await self.client.post(state_url)
222-
resp.raise_for_status()
223-
future_enveloped = Envelope[
224-
FileUploadCompleteFutureResponse
225-
].model_validate_json(resp.text)
226-
assert future_enveloped.data # nosec
227-
if future_enveloped.data.state == FileUploadCompleteState.NOK:
228-
msg = "upload not ready yet"
229-
raise ValueError(msg)
230-
231-
assert future_enveloped.data.e_tag # nosec
232-
_logger.debug(
233-
"multipart upload completed in %s, received %s",
234-
attempt.retry_state.retry_object.statistics,
235-
f"{future_enveloped.data.e_tag=}",
236-
)
237-
return future_enveloped.data.e_tag
238-
msg = f"Could not complete the upload for file '{file.filename}' (id: {file.id}) within the allocated time."
239-
raise HTTPException(
240-
status_code=status.HTTP_504_GATEWAY_TIMEOUT,
241-
detail=msg,
242-
)
215+
try:
216+
async for attempt in AsyncRetrying(
217+
reraise=True,
218+
wait=wait_fixed(1),
219+
stop=stop_after_delay(_POLL_TIMEOUT),
220+
retry=retry_if_exception_type(TryAgain),
221+
before_sleep=before_sleep_log(_logger, logging.DEBUG),
222+
):
223+
with attempt:
224+
resp = await self.client.post(state_url)
225+
resp.raise_for_status()
226+
future_enveloped = Envelope[
227+
FileUploadCompleteFutureResponse
228+
].model_validate_json(resp.text)
229+
assert future_enveloped.data # nosec
230+
if future_enveloped.data.state == FileUploadCompleteState.NOK:
231+
msg = "upload not ready yet"
232+
raise TryAgain()
233+
234+
assert future_enveloped.data.e_tag # nosec
235+
_logger.debug(
236+
"multipart upload completed in %s, received %s",
237+
attempt.retry_state.retry_object.statistics,
238+
f"{future_enveloped.data.e_tag=}",
239+
)
240+
return future_enveloped.data.e_tag
241+
except TryAgain as exc:
242+
raise BackendTimeoutError() from exc
243243

244244
@_exception_mapper(http_status_map={})
245245
async def abort_file_upload(self, *, user_id: int, file: File) -> None:

0 commit comments

Comments
 (0)