Skip to content

Commit 32ac020

Browse files
committed
handle task not found errors properly in api-server
1 parent 5e3e77f commit 32ac020

File tree

3 files changed

+56
-46
lines changed

3 files changed

+56
-46
lines changed

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

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import logging
2+
from contextlib import contextmanager
23
from typing import Annotated, Any
34

5+
from celery_library import task
6+
from celery_library.errors import TaskNotFoundError
47
from common_library.error_codes import create_error_code
58
from common_library.logging.logging_errors import create_troubleshooting_log_kwargs
69
from fastapi import APIRouter, Depends, FastAPI, HTTPException, status
@@ -18,6 +21,7 @@
1821
from servicelib.celery.models import TaskState, TaskUUID
1922
from servicelib.fastapi.dependencies import get_app
2023

24+
from ...exceptions.backend_errors import CeleryTaskNotFoundError
2125
from ...models.domain.celery_models import (
2226
ApiServerOwnerMetadata,
2327
)
@@ -42,6 +46,14 @@
4246
}
4347

4448

49+
@contextmanager
50+
def _exception_mapper(task_uuid: TaskUUID):
51+
try:
52+
yield
53+
except TaskNotFoundError as exc:
54+
raise CeleryTaskNotFoundError(task_uuid=task_uuid) from exc
55+
56+
4557
@router.get(
4658
"",
4759
response_model=ApiServerEnvelope[list[TaskGet]],
@@ -109,10 +121,11 @@ async def get_task_status(
109121
user_id=user_id,
110122
product_name=product_name,
111123
)
112-
task_status = await task_manager.get_task_status(
113-
owner_metadata=owner_metadata,
114-
task_uuid=TaskUUID(f"{task_uuid}"),
115-
)
124+
with _exception_mapper(task_uuid=task_uuid):
125+
task_status = await task_manager.get_task_status(
126+
owner_metadata=owner_metadata,
127+
task_uuid=TaskUUID(f"{task_uuid}"),
128+
)
116129

117130
return TaskStatus(
118131
task_progress=TaskProgress(
@@ -147,10 +160,11 @@ async def cancel_task(
147160
user_id=user_id,
148161
product_name=product_name,
149162
)
150-
await task_manager.cancel_task(
151-
owner_metadata=owner_metadata,
152-
task_uuid=TaskUUID(f"{task_uuid}"),
153-
)
163+
with _exception_mapper(task_uuid=task_uuid):
164+
await task_manager.cancel_task(
165+
owner_metadata=owner_metadata,
166+
task_uuid=TaskUUID(f"{task_uuid}"),
167+
)
154168

155169

156170
@router.get(
@@ -183,37 +197,38 @@ async def get_task_result(
183197
product_name=product_name,
184198
)
185199

186-
task_status = await task_manager.get_task_status(
187-
owner_metadata=owner_metadata,
188-
task_uuid=TaskUUID(f"{task_uuid}"),
189-
)
190-
191-
if not task_status.is_done:
192-
raise HTTPException(
193-
status_code=status.HTTP_404_NOT_FOUND,
194-
detail="Task result not available yet",
200+
with _exception_mapper(task_uuid=task_uuid):
201+
task_status = await task_manager.get_task_status(
202+
owner_metadata=owner_metadata,
203+
task_uuid=TaskUUID(f"{task_uuid}"),
195204
)
196205

197-
task_result = await task_manager.get_task_result(
198-
owner_metadata=owner_metadata,
199-
task_uuid=TaskUUID(f"{task_uuid}"),
200-
)
201-
202-
if task_status.task_state == TaskState.FAILURE:
203-
assert isinstance(task_result, Exception)
204-
user_error_msg = f"The execution of task {task_uuid} failed"
205-
support_id = create_error_code(task_result)
206-
_logger.exception(
207-
**create_troubleshooting_log_kwargs(
208-
user_error_msg,
209-
error=task_result,
210-
error_code=support_id,
211-
tip="Unexpected error in Celery",
206+
if not task_status.is_done:
207+
raise HTTPException(
208+
status_code=status.HTTP_404_NOT_FOUND,
209+
detail="Task result not available yet",
212210
)
211+
212+
task_result = await task_manager.get_task_result(
213+
owner_metadata=owner_metadata,
214+
task_uuid=TaskUUID(f"{task_uuid}"),
213215
)
214-
raise HTTPException(
215-
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
216-
detail=user_error_msg,
217-
)
216+
217+
if task_status.task_state == TaskState.FAILURE:
218+
assert isinstance(task_result, Exception)
219+
user_error_msg = f"The execution of task {task_uuid} failed"
220+
support_id = create_error_code(task_result)
221+
_logger.exception(
222+
**create_troubleshooting_log_kwargs(
223+
user_error_msg,
224+
error=task_result,
225+
error_code=support_id,
226+
tip="Unexpected error in Celery",
227+
)
228+
)
229+
raise HTTPException(
230+
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
231+
detail=user_error_msg,
232+
)
218233

219234
return TaskResult(result=task_result, error=None)

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
@@ -146,3 +146,8 @@ class LicensedItemCheckoutNotFoundError(BaseBackEndError):
146146
class JobAssetsMissingError(BaseBackEndError):
147147
msg_template = "Job assets missing for job {job_id}"
148148
status_code = status.HTTP_409_CONFLICT
149+
150+
151+
class CeleryTaskNotFoundError(BaseBackEndError):
152+
msg_template = "Task {task_uuid} not found"
153+
status_code = status.HTTP_404_NOT_FOUND

services/api-server/src/simcore_service_api_server/exceptions/handlers/__init__.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,6 @@ def setup(app: FastAPI, *, is_debug: bool = False):
4545
),
4646
)
4747

48-
app.add_exception_handler(
49-
TaskNotFoundError,
50-
make_handler_for_exception(
51-
TaskNotFoundError,
52-
status.HTTP_404_NOT_FOUND,
53-
error_message=MSG_CLIENT_ERROR_USER_FRIENDLY_TEMPLATE,
54-
add_exception_to_message=True,
55-
),
56-
)
57-
5848
app.add_exception_handler(
5949
CeleryError,
6050
make_handler_for_exception(

0 commit comments

Comments
 (0)