stompest is a full-featured STOMP 1.0, 1.1, and 1.2 implementation for Python 2.7 and Python 3 (versions 3.3 and higher) including both synchronous and asynchronous clients:
- The
sync.Stomp
client is dead simple. It does not assume anything about your concurrency model (thread vs process) or force you to use it any particular way. It gets out of your way and lets you do what you want. - The
twisted.Stomp
client is based on Twisted, a very mature and powerful asynchronous programming framework. It supports destination specific message and error handlers (with default "poison pill" error handling), concurrent message processing, graceful shutdown, and connect and disconnect timeouts.
Both clients support TLS/SSL for secure connections to ActiveMQ, and both clients make use of a generic set of components in the protocol
module, each of which can be used independently to roll your own STOMP client:
-
a wire-level STOMP frame parser
protocol.StompParser
and compilerprotocol.StompFrame
, -
a faithful implementation of the syntax of the STOMP protocol with a simple stateless function API in the
protocol.commands
module, -
a generic implementation of the STOMP session state semantics in
protocol.StompSession
, such as protocol version negotiation at connect time, heart-beating, transaction and subscription handling (including a generic subscription replay scheme which may be used to reconstruct the session's subscription state after a forced disconnect), -
and
protocol.StompFailoverTransport
, a failover transport URI scheme akin to the one used in ActiveMQ.
This package is thoroughly unit tested and production hardened for the functionality used by the current maintainer and by Mozes — persistent queueing on ActiveMQ. Minor enhancements may be required to use this STOMP adapter with other brokers.
- If you do not wish to use the asynchronous client (which depends on Twisted), stompest is fully self-contained.
- You can find all stompest releases on the Python Package Index. Just use the method you like most:
easy_install stompest
,pip install stompest
, orpython setup.py install
.
The stompest API is fully documented here.
To build the documentation, you'll need a source checkout, and then first install the documentation dependencies into your virtual environment:
(env) $ pip install -e .[doc]
Then you can build the documentation in the doc/
directory:
(env) $ cd doc/
(env) $ make html
The HTML documentation will be in the directory doc/stompest-doc
.
Feel free to open an issue here or post a question on the forum.
- Transport and client agnostic.
- Full-featured implementation of all STOMP client commands.
- Client-side handling of STOMP commands received from the broker.
- Stateless and simple function API.
- Manages the state of a connection.
- Replays subscriptions upon reconnect.
- Heart-beat handling.
- Mimicks the failover transport behavior of the native ActiveMQ Java client.
- Produces a (possibly infinite) sequence of broker network addresses and connect delay times.
- Abstract frame definition.
- Transformation between these abstract frames and a wire-level byte stream of STOMP frames.
- Built on top of the abstract layers, the synchronous client adds a TCP connection and a synchronous API.
- The concurrency scheme (synchronous, threaded, ...) is free to choose by the user.
- Based on the Twisted asynchronous framework.
- Fully unit-tested including a simulated STOMP broker.
- Graceful shutdown: on disconnect or error, the client stops processing new messages and waits for all outstanding message handlers to finish before issuing the
DISCONNECT
command. - Error handling - fully customizable on a per-subscription level:
- Disconnect: if you do not configure an errorDestination and an exception propagates up from a message handler, then the client will gracefully disconnect. This is effectively a
NACK
for the message (actually, disconnecting is the only way toNACK
in STOMP 1.0). You can configure ActiveMQ with a redelivery policy to avoid the "poison pill" scenario where the broker keeps redelivering a bad message infinitely. - Default error handling: passing an error destination parameter at subscription time will cause unhandled messages to be forwarded to that destination and then
ACK
ed. - Custom hook: you can override the default behavior with any customized error handling scheme.
- Disconnect: if you do not configure an errorDestination and an exception propagates up from a message handler, then the client will gracefully disconnect. This is effectively a
- Separately configurable timeouts for wire-level connection, the broker's
CONNECTED
reply frame, and graceful disconnect (in-flight handlers that do not finish in time).
- Version 1.x of stompest was written by Roger Hoover (@theduderog) at Mozes and deployed in their production environment.
- Kudos to Oisin Mulvihill, the developer of [stomper] (https://github.com/oisinmulvihill/stomper)! His idea of an abstract representation of the STOMP protocol lives on in stompest.
I am no longer using stompest actively, because I have moved on inside my enterprise — which still uses stompest in production but has no-one with both the skill and time to maintain it — to a non-coding strategic/leadership position. Therefore, it is more of a hobby, and I have to rebuild my coding, testing and building environment from scratch every few months which rather sucks.
A few random thoughts:
- I still do accept (and test) pull requests and bugfixes (if they come with complete and working unit and integration tests), but the Python 3 port was my last big effort for stompest.
- I believe that fully implementing the (half-complete) SSL/TLS capability is the most urgent enhancement because apart of that I consider stompest pretty much feature complete and very stable up to Python 3.6; the rate of newly discovered bugs is very low indeed.
- A port of the Twisted client to
asyncio
would make a lot of sense. If someone creates a pull request, I'll test it and create a new PyPI package. - If someone would like to take over the project, please let me know. I would actively consult as an éminence grise.