Skip to content

Commit 90a1f10

Browse files
author
Andrei Neagu
committed
updating interface
1 parent e32e933 commit 90a1f10

File tree

7 files changed

+29
-129
lines changed

7 files changed

+29
-129
lines changed

packages/service-library/src/servicelib/fastapi/long_running_tasks/_client.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import functools
33
import logging
44
import warnings
5-
from typing import Any, Awaitable, Callable, Final
5+
from collections.abc import Awaitable, Callable
6+
from typing import Any, Final
67

78
from fastapi import FastAPI, status
89
from httpx import AsyncClient, HTTPError
@@ -13,13 +14,8 @@
1314
from tenacity.stop import stop_after_attempt
1415
from tenacity.wait import wait_exponential
1516

16-
from ...long_running_tasks._errors import GenericClientError, TaskClientResultError
17-
from ...long_running_tasks._models import (
18-
ClientConfiguration,
19-
TaskId,
20-
TaskResult,
21-
TaskStatus,
22-
)
17+
from ...long_running_tasks._errors import GenericClientError
18+
from ...long_running_tasks._models import ClientConfiguration, TaskId, TaskStatus
2319

2420
DEFAULT_HTTP_REQUESTS_TIMEOUT: Final[PositiveFloat] = 15
2521

@@ -85,7 +81,7 @@ def log_it(retry_state: RetryCallState) -> None:
8581

8682

8783
def retry_on_http_errors(
88-
request_func: Callable[..., Awaitable[Any]]
84+
request_func: Callable[..., Awaitable[Any]],
8985
) -> Callable[..., Awaitable[Any]]:
9086
"""
9187
Will retry the request on `httpx.HTTPError`.
@@ -173,10 +169,7 @@ async def get_task_result(
173169
body=result.text,
174170
)
175171

176-
task_result = TaskResult.model_validate(result.json())
177-
if task_result.error is not None:
178-
raise TaskClientResultError(message=task_result.error)
179-
return task_result.result
172+
return result.json()
180173

181174
@retry_on_http_errors
182175
async def cancel_and_delete_task(

packages/service-library/src/servicelib/fastapi/long_running_tasks/_routes.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Annotated, Any
22

3-
from fastapi import APIRouter, Depends, Query, Request, status
3+
from fastapi import APIRouter, Depends, Request, status
44

55
from ...long_running_tasks._errors import TaskNotCompletedError, TaskNotFoundError
66
from ...long_running_tasks._models import TaskGet, TaskId, TaskResult, TaskStatus
@@ -60,16 +60,10 @@ async def get_task_result(
6060
request: Request,
6161
task_id: TaskId,
6262
tasks_manager: Annotated[TasksManager, Depends(get_tasks_manager)],
63-
*,
64-
return_exception: Annotated[bool, Query()] = False,
6563
) -> TaskResult | Any:
6664
assert request # nosec
67-
# TODO: refactor this to use same as in https://github.com/ITISFoundation/osparc-simcore/issues/3265
6865
try:
69-
if return_exception:
70-
task_result = tasks_manager.get_task_result(task_id, with_task_context=None)
71-
else:
72-
task_result = tasks_manager.get_task_result_old(task_id=task_id)
66+
task_result = tasks_manager.get_task_result(task_id, with_task_context=None)
7367
await tasks_manager.remove_task(
7468
task_id, with_task_context=None, reraise_errors=False
7569
)

packages/service-library/src/servicelib/fastapi/long_running_tasks/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ async def _wait_for_completion(
9797

9898
@retry(**_DEFAULT_FASTAPI_RETRY_POLICY)
9999
async def _task_result(session: httpx.AsyncClient, result_url: URL) -> Any:
100-
response = await session.get(f"{result_url}", params={"return_exception": True})
100+
response = await session.get(f"{result_url}")
101101
response.raise_for_status()
102102
if response.status_code != status.HTTP_204_NO_CONTENT:
103103
return unwrap_envelope_if_required(response.json())

packages/service-library/src/servicelib/long_running_tasks/_task.py

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
TaskNotCompletedError,
2323
TaskNotFoundError,
2424
)
25-
from ._models import TaskId, TaskName, TaskResult, TaskStatus, TrackedTask
25+
from ._models import TaskId, TaskName, TaskStatus, TrackedTask
2626

2727
logger = logging.getLogger(__name__)
2828

@@ -241,36 +241,6 @@ def get_task_result(
241241
# the task was cancelled
242242
raise TaskCancelledError(task_id=task_id) from exc
243243

244-
def get_task_result_old(self, task_id: TaskId) -> TaskResult:
245-
"""
246-
returns: the result of the task
247-
248-
raises TaskNotFoundError if the task cannot be found
249-
"""
250-
tracked_task = self._get_tracked_task(task_id, {})
251-
252-
if not tracked_task.task.done():
253-
raise TaskNotCompletedError(task_id=task_id)
254-
255-
error: TaskExceptionError | TaskCancelledError
256-
try:
257-
exception = tracked_task.task.exception()
258-
if exception is not None:
259-
formatted_traceback = "\n".join(
260-
traceback.format_tb(exception.__traceback__)
261-
)
262-
error = TaskExceptionError(
263-
task_id=task_id, exception=exception, traceback=formatted_traceback
264-
)
265-
logger.warning("Task %s finished with error: %s", task_id, f"{error}")
266-
return TaskResult(result=None, error=f"{error}")
267-
except asyncio.CancelledError:
268-
error = TaskCancelledError(task_id=task_id)
269-
logger.warning("Task %s was cancelled", task_id)
270-
return TaskResult(result=None, error=f"{error}")
271-
272-
return TaskResult(result=tracked_task.task.result(), error=None)
273-
274244
async def cancel_task(
275245
self, task_id: TaskId, with_task_context: TaskContext | None
276246
) -> None:
@@ -292,7 +262,7 @@ async def _cancel_asyncio_task(
292262
await asyncio.wait_for(
293263
_await_task(task), timeout=self._cancel_task_timeout_s
294264
)
295-
except asyncio.TimeoutError:
265+
except TimeoutError:
296266
logger.warning(
297267
"Timed out while awaiting for cancellation of '%s'", reference
298268
)
@@ -354,12 +324,12 @@ async def close(self) -> None:
354324

355325

356326
class TaskProtocol(Protocol):
357-
async def __call__(self, progress: TaskProgress, *args: Any, **kwargs: Any) -> Any:
358-
...
327+
async def __call__(
328+
self, progress: TaskProgress, *args: Any, **kwargs: Any
329+
) -> Any: ...
359330

360331
@property
361-
def __name__(self) -> str:
362-
...
332+
def __name__(self) -> str: ...
363333

364334

365335
def start_task(

packages/service-library/tests/fastapi/long_running_tasks/test_long_running_tasks.py

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ async def _caller(app: FastAPI, client: AsyncClient, **query_kwargs) -> TaskId:
103103

104104

105105
@pytest.fixture
106-
def wait_for_task() -> Callable[
107-
[FastAPI, AsyncClient, TaskId, TaskContext], Awaitable[None]
108-
]:
106+
def wait_for_task() -> (
107+
Callable[[FastAPI, AsyncClient, TaskId, TaskContext], Awaitable[None]]
108+
):
109109
async def _waiter(
110110
app: FastAPI,
111111
client: AsyncClient,
@@ -183,9 +183,7 @@ async def test_workflow(
183183
result = await client.get(f"{result_url}")
184184
# NOTE: this is DIFFERENT than with aiohttp where we return the real result
185185
assert result.status_code == status.HTTP_200_OK
186-
task_result = long_running_tasks.server.TaskResult.model_validate(result.json())
187-
assert not task_result.error
188-
assert task_result.result == [f"{x}" for x in range(10)]
186+
assert result.json() == [f"{x}" for x in range(10)]
189187
# getting the result again should raise a 404
190188
result = await client.get(result_url)
191189
assert result.status_code == status.HTTP_404_NOT_FOUND
@@ -220,19 +218,9 @@ async def test_failing_task_returns_error(
220218
await wait_for_task(app, client, task_id, {})
221219
# get the result
222220
result_url = app.url_path_for("get_task_result", task_id=task_id)
223-
result = await client.get(f"{result_url}")
224-
assert result.status_code == status.HTTP_200_OK
225-
task_result = long_running_tasks.server.TaskResult.model_validate(result.json())
226-
227-
assert not task_result.result
228-
assert task_result.error
229-
assert task_result.error.startswith(f"Task {task_id} finished with exception: ")
230-
assert 'raise RuntimeError("We were asked to fail!!")' in task_result.error
231-
# NOTE: this is not yet happening with fastapi version of long running task
232-
# assert "errors" in task_result.error
233-
# assert len(task_result.error["errors"]) == 1
234-
# assert task_result.error["errors"][0]["code"] == "RuntimeError"
235-
# assert task_result.error["errors"][0]["message"] == "We were asked to fail!!"
221+
with pytest.raises(RuntimeError) as exec_info:
222+
await client.get(f"{result_url}")
223+
assert f"{exec_info.value}" == "We were asked to fail!!"
236224

237225

238226
async def test_get_results_before_tasks_finishes_returns_404(

packages/service-library/tests/fastapi/long_running_tasks/test_long_running_tasks_context_manager.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
# pylint: disable=unused-argument
33

44
import asyncio
5-
from typing import AsyncIterable, Final
5+
from collections.abc import AsyncIterable
6+
from typing import Final
67

78
import pytest
89
from asgi_lifespan import LifespanManager
@@ -24,9 +25,10 @@
2425
get_tasks_manager,
2526
)
2627
from servicelib.fastapi.long_running_tasks.server import setup as setup_server
27-
from servicelib.fastapi.long_running_tasks.server import start_task
28+
from servicelib.fastapi.long_running_tasks.server import (
29+
start_task,
30+
)
2831
from servicelib.long_running_tasks._errors import (
29-
TaskClientResultError,
3032
TaskClientTimeoutError,
3133
)
3234

@@ -149,16 +151,15 @@ async def test_task_result_task_result_is_an_error(
149151

150152
url = TypeAdapter(AnyHttpUrl).validate_python("http://backgroud.testserver.io/")
151153
client = Client(app=bg_task_app, async_client=async_client, base_url=url)
152-
with pytest.raises(TaskClientResultError) as exec_info:
154+
with pytest.raises(RuntimeError) as exec_info:
153155
async with periodic_task_result(
154156
client,
155157
task_id,
156158
task_timeout=10,
157159
status_poll_interval=TASK_SLEEP_INTERVAL / 3,
158160
):
159161
pass
160-
assert f"{exec_info.value}".startswith(f"Task {task_id} finished with exception:")
161-
assert "I am failing as requested" in f"{exec_info.value}"
162+
assert f"{exec_info.value}" == "I am failing as requested"
162163
await _assert_task_removed(async_client, task_id, router_prefix)
163164

164165

packages/service-library/tests/long_running_tasks/test_long_running_tasks_task.py

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from servicelib.long_running_tasks._models import (
2222
ProgressPercent,
2323
TaskProgress,
24-
TaskResult,
2524
TaskStatus,
2625
)
2726
from servicelib.long_running_tasks._task import TasksManager, start_task
@@ -108,8 +107,6 @@ async def test_task_is_auto_removed(
108107
tasks_manager.get_task_status(task_id, with_task_context=None)
109108
with pytest.raises(TaskNotFoundError):
110109
tasks_manager.get_task_result(task_id, with_task_context=None)
111-
with pytest.raises(TaskNotFoundError):
112-
tasks_manager.get_task_result_old(task_id)
113110

114111

115112
async def test_checked_task_is_not_auto_removed(tasks_manager: TasksManager):
@@ -156,9 +153,6 @@ async def test_get_result_of_unfinished_task_raises(tasks_manager: TasksManager)
156153
with pytest.raises(TaskNotCompletedError):
157154
tasks_manager.get_task_result(task_id, with_task_context=None)
158155

159-
with pytest.raises(TaskNotCompletedError):
160-
tasks_manager.get_task_result_old(task_id)
161-
162156

163157
async def test_unique_task_already_running(tasks_manager: TasksManager):
164158
async def unique_task(task_progress: TaskProgress):
@@ -214,13 +208,6 @@ async def test_get_result(tasks_manager: TasksManager):
214208
assert result == 42
215209

216210

217-
async def test_get_result_old(tasks_manager: TasksManager):
218-
task_id = start_task(tasks_manager=tasks_manager, task=fast_background_task)
219-
await asyncio.sleep(0.1)
220-
result = tasks_manager.get_task_result_old(task_id)
221-
assert result == TaskResult(result=42, error=None)
222-
223-
224211
async def test_get_result_missing(tasks_manager: TasksManager):
225212
with pytest.raises(TaskNotFoundError) as exec_info:
226213
tasks_manager.get_task_result("missing_task_id", with_task_context=None)
@@ -238,20 +225,6 @@ async def test_get_result_finished_with_error(tasks_manager: TasksManager):
238225
tasks_manager.get_task_result(task_id, with_task_context=None)
239226

240227

241-
async def test_get_result_old_finished_with_error(tasks_manager: TasksManager):
242-
task_id = start_task(tasks_manager=tasks_manager, task=failing_background_task)
243-
# wait for result
244-
async for attempt in AsyncRetrying(**_RETRY_PARAMS):
245-
with attempt:
246-
assert tasks_manager.get_task_status(task_id, with_task_context=None).done
247-
248-
task_result = tasks_manager.get_task_result_old(task_id)
249-
assert task_result.result is None
250-
assert task_result.error is not None
251-
assert task_result.error.startswith(f"Task {task_id} finished with exception:")
252-
assert "failing asap" in task_result.error
253-
254-
255228
async def test_get_result_task_was_cancelled_multiple_times(
256229
tasks_manager: TasksManager,
257230
):
@@ -270,23 +243,6 @@ async def test_get_result_task_was_cancelled_multiple_times(
270243
tasks_manager.get_task_result(task_id, with_task_context=None)
271244

272245

273-
async def test_get_result_old_task_was_cancelled_multiple_times(
274-
tasks_manager: TasksManager,
275-
):
276-
task_id = start_task(
277-
tasks_manager=tasks_manager,
278-
task=a_background_task,
279-
raise_when_finished=False,
280-
total_sleep=10,
281-
)
282-
for _ in range(5):
283-
await tasks_manager.cancel_task(task_id, with_task_context=None)
284-
285-
task_result = tasks_manager.get_task_result_old(task_id)
286-
assert task_result.result is None
287-
assert task_result.error == f"Task {task_id} was cancelled before completing"
288-
289-
290246
async def test_remove_task(tasks_manager: TasksManager):
291247
task_id = start_task(
292248
tasks_manager=tasks_manager,
@@ -300,8 +256,6 @@ async def test_remove_task(tasks_manager: TasksManager):
300256
tasks_manager.get_task_status(task_id, with_task_context=None)
301257
with pytest.raises(TaskNotFoundError):
302258
tasks_manager.get_task_result(task_id, with_task_context=None)
303-
with pytest.raises(TaskNotFoundError):
304-
tasks_manager.get_task_result_old(task_id)
305259

306260

307261
async def test_remove_task_with_task_context(tasks_manager: TasksManager):

0 commit comments

Comments
 (0)