Skip to content

Commit 3883c88

Browse files
authored
Remove MessageEvent.await_with_auto_ack() (#9)
1 parent d286b77 commit 3883c88

File tree

4 files changed

+8
-76
lines changed

4 files changed

+8
-76
lines changed

Justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
default: install lint check-types test
1+
default: install lint check-types test test-integration
22

33
install:
44
poetry install --sync

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ async with asyncio.TaskGroup() as task_group:
8888
async for event in client.listen_to_events():
8989
match event:
9090
case stompman.MessageEvent(body=body):
91-
task_group.create_task(event.await_with_auto_ack(handle_message(body)))
91+
task_group.create_task(handle_message(body))
9292
case stompman.ErrorEvent(message_header=short_description, body=body):
9393
logger.error(
9494
"Received an error from server", short_description=short_description, body=body, event=event
@@ -97,16 +97,17 @@ async with asyncio.TaskGroup() as task_group:
9797
task_group.create_task(update_healthcheck_status())
9898

9999

100-
async def handle_message(body: bytes) -> None:
100+
async def handle_message(event: stompman.MessageEvent) -> None:
101101
try:
102-
validated_message = MyMessageModel.model_validate_json(body)
102+
validated_message = MyMessageModel.model_validate_json(event.body)
103103
await run_business_logic(validated_message)
104104
except Exception:
105-
logger.exception("Failed to handle message", body=body)
105+
await event.nack()
106+
logger.exception("Failed to handle message", event=event)
107+
else:
108+
await event.ack()
106109
```
107110

108-
You can pass awaitable object (coroutine, for example) to `Message.await_with_auto_ack()`. In case of error, it will catch any exceptions, send NACK to server and propagate them to the caller. Otherwise, it will send ACK, acknowledging the message was processed successfully.
109-
110111
### Cleaning Up
111112

112113
stompman takes care of cleaning up resources automatically. When you leave the context of async context managers `stompman.Client()`, `client.subscribe()`, or `client.enter_transaction()`, the necessary frames will be sent to the server.

stompman/listening_events.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from collections.abc import Awaitable
21
from dataclasses import dataclass, field
32
from typing import TYPE_CHECKING
43

@@ -37,21 +36,6 @@ async def nack(self) -> None:
3736
)
3837
)
3938

40-
async def await_with_auto_ack(
41-
self, awaitable: Awaitable[None], exception_types: tuple[type[Exception],] = (Exception,)
42-
) -> None:
43-
called_nack = False
44-
45-
try:
46-
await awaitable
47-
except exception_types:
48-
await self.nack()
49-
called_nack = True
50-
raise
51-
finally:
52-
if not called_nack:
53-
await self.ack()
54-
5539

5640
@dataclass
5741
class ErrorEvent:

tests/test_client.py

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -346,59 +346,6 @@ async def test_ack_nack() -> None:
346346
assert_frames_between_lifespan_match(collected_frames, [message_frame, nack_frame, ack_frame])
347347

348348

349-
def get_mocked_message_event() -> tuple[MessageEvent, mock.AsyncMock, mock.AsyncMock]:
350-
ack_mock, nack_mock = mock.AsyncMock(), mock.AsyncMock()
351-
352-
class CustomMessageEvent(MessageEvent):
353-
ack = ack_mock
354-
nack = nack_mock
355-
356-
return (
357-
CustomMessageEvent(
358-
_frame=MessageFrame(
359-
headers={"destination": "destination", "message-id": "message-id", "subscription": "subscription"},
360-
body=b"",
361-
),
362-
_client=mock.Mock(),
363-
),
364-
ack_mock,
365-
nack_mock,
366-
)
367-
368-
369-
async def test_message_event_await_with_auto_ack_nack() -> None:
370-
event, ack, nack = get_mocked_message_event()
371-
372-
async def raises_runtime_error() -> None: # noqa: RUF029
373-
raise RuntimeError
374-
375-
with suppress(RuntimeError):
376-
await event.await_with_auto_ack(raises_runtime_error(), exception_types=(Exception,))
377-
378-
ack.assert_not_called()
379-
nack.assert_called_once_with()
380-
381-
382-
async def test_message_event_await_with_auto_ack_ack_raises() -> None:
383-
event, ack, nack = get_mocked_message_event()
384-
385-
async def func() -> None: # noqa: RUF029
386-
raise Exception # noqa: TRY002
387-
388-
with suppress(Exception):
389-
await event.await_with_auto_ack(func(), exception_types=(RuntimeError,))
390-
391-
ack.assert_called_once_with()
392-
nack.assert_not_called()
393-
394-
395-
async def test_message_event_await_with_auto_ack_ack_ok() -> None:
396-
event, ack, nack = get_mocked_message_event()
397-
await event.await_with_auto_ack(mock.AsyncMock()())
398-
ack.assert_called_once_with()
399-
nack.assert_not_called()
400-
401-
402349
async def test_send_message_and_enter_transaction_ok(monkeypatch: pytest.MonkeyPatch) -> None:
403350
body = b"hello"
404351
destination = "/queue/test"

0 commit comments

Comments
 (0)