Skip to content

Commit 9512562

Browse files
committed
fix: do not parse return value of errored tasks
When a task fails, the receiver stores a result with `is_err=True` and `return_value=None`. `AsyncTaskiqTask.get_result` still tried to validate that `None` against the task's return annotation, so every failed task with a non-optional return type logged a misleading "Cannot parse return type into ..." warning on the client side. Skip the validation when the result is an error: there is no return value to parse, and the actual failure is already available in `result.error`. Closes: #479
1 parent a00e4b0 commit 9512562

2 files changed

Lines changed: 43 additions & 2 deletions

File tree

‎taskiq/task.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ async def get_result(self, with_logs: bool = False) -> "TaskiqResult[_ReturnType
6161
self.task_id,
6262
with_logs=with_logs,
6363
)
64-
if self.return_type is not None:
64+
# Errored tasks have no return value to validate,
65+
# so parsing would only produce a misleading warning.
66+
if self.return_type is not None and not res.is_err:
6567
try:
6668
res.return_value = parse_obj_as(
6769
self.return_type,

‎tests/test_task.py‎

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import logging
12
import uuid
2-
from typing import TypeVar
3+
from typing import Any, TypeVar
34

45
import pytest
56
from pydantic import BaseModel
@@ -68,3 +69,41 @@ class MyResult(BaseModel):
6869
sent_task = AsyncTaskiqTask(test_id, res_back, MyResult)
6970
parsed = await sent_task.wait_result()
7071
assert isinstance(parsed.return_value, MyResult)
72+
73+
74+
async def test_res_parsing_skipped_on_error(caplog: pytest.LogCaptureFixture) -> None:
75+
res_back: AsyncResultBackend[Any] = SerializingBackend(serializers.JSONSerializer())
76+
test_id = str(uuid.uuid4())
77+
await res_back.set_result(
78+
test_id,
79+
TaskiqResult(
80+
is_err=True,
81+
return_value=None,
82+
execution_time=0.0,
83+
),
84+
)
85+
sent_task: AsyncTaskiqTask[Any] = AsyncTaskiqTask(test_id, res_back, int)
86+
with caplog.at_level(logging.WARNING, logger="taskiq.task"):
87+
parsed = await sent_task.wait_result()
88+
assert parsed.is_err
89+
assert parsed.return_value is None
90+
assert "Cannot parse return type" not in caplog.text
91+
92+
93+
async def test_res_parsing_failure(caplog: pytest.LogCaptureFixture) -> None:
94+
res_back: AsyncResultBackend[Any] = SerializingBackend(serializers.JSONSerializer())
95+
test_id = str(uuid.uuid4())
96+
await res_back.set_result(
97+
test_id,
98+
TaskiqResult(
99+
is_err=False,
100+
return_value="not-an-int",
101+
execution_time=0.0,
102+
),
103+
)
104+
sent_task: AsyncTaskiqTask[Any] = AsyncTaskiqTask(test_id, res_back, int)
105+
with caplog.at_level(logging.WARNING, logger="taskiq.task"):
106+
parsed = await sent_task.wait_result()
107+
assert not parsed.is_err
108+
assert parsed.return_value == "not-an-int"
109+
assert "Cannot parse return type" in caplog.text

0 commit comments

Comments
 (0)