Python STOMP client with pleasant API
Project description
stompman
A Python client for STOMP asynchronous messaging protocol that is:
- asynchronous,
- not abandoned,
- has typed, modern, comprehensible API.
How To Use
Before you start using stompman, make sure you have it installed:
uv add stompman
poetry add stompman
Initialize a client:
async with stompman.Client(
servers=[
stompman.ConnectionParameters(host="171.0.0.1", port=61616, login="user1", passcode="passcode1"),
stompman.ConnectionParameters(host="172.0.0.1", port=61616, login="user2", passcode="passcode2"),
],
# SSL — can be either `None` (default), `True`, or `ssl.SSLContext'
ssl=None,
# Error frame handler:
on_error_frame=lambda error_frame: print(error_frame.body),
# Optional parameters with sensible defaults:
heartbeat=stompman.Heartbeat(will_send_interval_ms=1000, want_to_receive_interval_ms=1000),
connect_retry_attempts=3,
connect_retry_interval=1,
connect_timeout=2,
connection_confirmation_timeout=2,
disconnect_confirmation_timeout=2,
read_timeout=2,
write_retry_attempts=3,
check_server_alive_interval_factor=3,
) as client:
...
Sending Messages
To send a message, use the following code:
await client.send(b"hi there!", destination="DLQ", headers={"persistent": "true"})
Or, to send messages in a transaction:
async with client.begin() as transaction:
for _ in range(10):
await transaction.send(body=b"hi there!", destination="DLQ", headers={"persistent": "true"})
await asyncio.sleep(0.1)
Listening for Messages
Now, let's subscribe to a destination and listen for messages:
async def handle_message_from_dlq(message_frame: stompman.MessageFrame) -> None:
print(message_frame.body)
await client.subscribe("DLQ", handle_message_from_dlq, on_suppressed_exception=print)
Entered stompman.Client will block forever waiting for messages if there are any active subscriptions.
Sometimes it's useful to avoid that:
dlq_subscription = await client.subscribe("DLQ", handle_message_from_dlq, on_suppressed_exception=print)
await dlq_subscription.unsubscribe()
By default, subscription have ACK mode "client-individual". If handler successfully processes the message, an ACK frame will be sent. If handler raises an exception, a NACK frame will be sent. You can catch (and log) exceptions using on_suppressed_exception parameter:
await client.subscribe(
"DLQ",
handle_message_from_dlq,
on_suppressed_exception=lambda exception, message_frame: print(exception, message_frame),
)
You can change the ack mode used by specifying the ack parameter:
# Server will assume that all messages sent to the subscription before the ACK'ed message are received and processed:
await client.subscribe("DLQ", handle_message_from_dlq, ack="client", on_suppressed_exception=print)
# Server will assume that messages are received as soon as it send them to client:
await client.subscribe("DLQ", handle_message_from_dlq, ack="auto", on_suppressed_exception=print)
You can pass custom headers to client.subscribe():
await client.subscribe("DLQ", handle_message_from_dlq, ack="client", headers={"selector": "location = 'Europe'"}, on_suppressed_exception=print)
Handling ACK/NACKs yourself
If you want to send ACK and NACK frames yourself, you can use client.subscribe_with_manual_ack():
async def handle_message_from_dlq(message_frame: stompman.AckableMessageFrame) -> None:
print(message_frame.body)
await message_frame.ack()
await client.subscribe_with_manual_ack("DLQ", handle_message_from_dlq, ack="client")
Note that this way exceptions won't be suppressed automatically.
Cleaning Up
stompman takes care of cleaning up resources automatically. When you leave the context of async context managers stompman.Client(), or client.begin(), the necessary frames will be sent to the server.
Handling Connectivity Issues
-
If multiple servers were provided, stompman will attempt to connect to each one simultaneously and will use the first that succeeds. If all servers fail to connect, an
stompman.FailedAllConnectAttemptsErrorwill be raised. In normal situation it doesn't need to be handled: tune retry and timeout parameters instompman.Client()to your needs. -
When connection is lost, stompman will attempt to handle it automatically.
stompman.FailedAllConnectAttemptsErrorwill be raised if all connection attempts fail.stompman.FailedAllWriteAttemptsErrorwill be raised if connection succeeds but sending a frame or heartbeat lead to losing connection. -
To implement health checks, use
stompman.Client.is_alive()— it will returnTrueif everything is OK andFalseif server is not responding.
...and caveats
- stompman supports Python 3.11 and newer.
- It implements STOMP 1.2 — the latest version of the protocol.
- Heartbeats are required, and sent automatically in background (defaults to 1 second).
Also, I want to pointed out that:
- Protocol parsing is inspired by aiostomp (meaning: consumed by me and refactored from).
- stompman is tested and used with ActiveMQ Artemis and ActiveMQ Classic.
- Caveat: a message sent by a Stomp client is converted into a JMS
TextMessage/BytesMessagebased on thecontent-lengthheader (see the docs here). In order to send aTextMessage,Client.sendneeds to be invoked withadd_content_lengthheader set toFalse
- Caveat: a message sent by a Stomp client is converted into a JMS
- Specification says that headers in CONNECT and CONNECTED frames shouldn't be escaped for backwards compatibility. stompman escapes headers in CONNECT frame (outcoming), but does not unescape headers in CONNECTED (outcoming).
FastStream STOMP broker
An implementation of STOMP broker for FastStream.
Examples
See examples in examples/.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stompman-2.1.0.tar.gz.
File metadata
- Download URL: stompman-2.1.0.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9a5f8b34be862f3e4bafda9fed1593c604888d2e040ffbf9204e19b91c4fd05
|
|
| MD5 |
4b6b614dca50c1f1504d63ebb99753b2
|
|
| BLAKE2b-256 |
57c42656eb7ce12b67e6086e13b280db6391f9ae7dc8eeda8fbd826dc319fdba
|
File details
Details for the file stompman-2.1.0-py3-none-any.whl.
File metadata
- Download URL: stompman-2.1.0-py3-none-any.whl
- Upload date:
- Size: 18.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55fd382191ac3e5e2d84b983d9fceae98d161541081396bd77654cc3379ad7a1
|
|
| MD5 |
faf2676e490137291351b7a4181f8997
|
|
| BLAKE2b-256 |
ce8ce622d6ae88c6e38caa93184d92d8dc67e538484a390a93c517a9719f8596
|