Skip to content

Commit c88ffa2

Browse files
committed
Keep retry exception filters reusable
1 parent f08a54a commit c88ffa2

3 files changed

Lines changed: 111 additions & 2 deletions

File tree

‎taskiq/middlewares/simple_retry_middleware.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ def __init__(
2424
self.default_retry_count = default_retry_count
2525
self.default_retry_label = default_retry_label
2626
self.no_result_on_retry = no_result_on_retry
27-
self.types_of_exceptions = types_of_exceptions
27+
self.types_of_exceptions = (
28+
tuple(types_of_exceptions) if types_of_exceptions is not None else None
29+
)
2830

2931
def _get_types_of_exceptions(
3032
self,

‎taskiq/middlewares/smart_retry_middleware.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ def __init__(
6161
self.use_delay_exponent = use_delay_exponent
6262
self.max_delay_exponent = max_delay_exponent
6363
self.schedule_source = schedule_source
64-
self.types_of_exceptions = types_of_exceptions
64+
self.types_of_exceptions = (
65+
tuple(types_of_exceptions) if types_of_exceptions is not None else None
66+
)
6567

6668
if not isinstance(schedule_source, (ScheduleSource, type(None))):
6769
raise TypeError(
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
from collections.abc import Iterable
2+
from typing import Any
3+
4+
import pytest
5+
6+
from taskiq import (
7+
InMemoryBroker,
8+
SimpleRetryMiddleware,
9+
SmartRetryMiddleware,
10+
TaskiqMessage,
11+
TaskiqResult,
12+
)
13+
from taskiq.message import BrokerMessage
14+
15+
16+
class RecordingBroker(InMemoryBroker):
17+
def __init__(self) -> None:
18+
super().__init__()
19+
self.sent: list[BrokerMessage] = []
20+
21+
async def kick(self, message: BrokerMessage) -> None:
22+
self.sent.append(message)
23+
24+
25+
@pytest.mark.parametrize(
26+
"middleware_class",
27+
[SimpleRetryMiddleware, SmartRetryMiddleware],
28+
)
29+
@pytest.mark.parametrize("filter_kind", ["generator", "list", "empty", "none"])
30+
async def test_exception_filter_is_reusable(
31+
middleware_class: type[SimpleRetryMiddleware] | type[SmartRetryMiddleware],
32+
filter_kind: str,
33+
) -> None:
34+
exception_types: Iterable[type[BaseException]] | None
35+
if filter_kind == "generator":
36+
exception_types = (kind for kind in [ValueError])
37+
elif filter_kind == "list":
38+
exception_types = [ValueError]
39+
elif filter_kind == "empty":
40+
exception_types = iter([])
41+
else:
42+
exception_types = None
43+
44+
broker = RecordingBroker()
45+
middleware = middleware_class(
46+
default_retry_label=True,
47+
types_of_exceptions=exception_types,
48+
)
49+
broker.with_middlewares(middleware)
50+
try:
51+
for task_id in ["first", "second"]:
52+
error = ValueError("retry")
53+
message = TaskiqMessage(
54+
task_id=task_id,
55+
task_name="test",
56+
labels={},
57+
args=[],
58+
kwargs={},
59+
)
60+
result: TaskiqResult[Any] = TaskiqResult(
61+
is_err=True,
62+
log=None,
63+
return_value=None,
64+
execution_time=0,
65+
error=error,
66+
)
67+
await middleware.on_error(message, result, error)
68+
assert len(broker.sent) == (0 if filter_kind == "empty" else 2)
69+
finally:
70+
await broker.shutdown()
71+
72+
73+
@pytest.mark.parametrize(
74+
"middleware_class",
75+
[SimpleRetryMiddleware, SmartRetryMiddleware],
76+
)
77+
async def test_nonmatching_error_does_not_consume_filter(
78+
middleware_class: type[SimpleRetryMiddleware] | type[SmartRetryMiddleware],
79+
) -> None:
80+
broker = RecordingBroker()
81+
middleware = middleware_class(
82+
default_retry_label=True,
83+
types_of_exceptions=(kind for kind in [ValueError]),
84+
)
85+
broker.with_middlewares(middleware)
86+
try:
87+
for error in [TypeError("skip"), ValueError("retry")]:
88+
message = TaskiqMessage(
89+
task_id=str(type(error)),
90+
task_name="test",
91+
labels={},
92+
args=[],
93+
kwargs={},
94+
)
95+
result: TaskiqResult[Any] = TaskiqResult(
96+
is_err=True,
97+
log=None,
98+
return_value=None,
99+
execution_time=0,
100+
error=error,
101+
)
102+
await middleware.on_error(message, result, error)
103+
assert len(broker.sent) == 1
104+
finally:
105+
await broker.shutdown()

0 commit comments

Comments
 (0)