AMQPStorm
repository·main·Indexed 42 days ago
https://github.com/eandersson/amqpstormA thread-safe Python 3 client and management library for RabbitMQ. It provides the ManagementApi for broker administration—including management of queues, exchanges, users, and virtual hosts—as well as tools for implementing robust AMQP consumers, publishers, and RPC patterns.
What's inside AMQPStorm
- AMQPStorm is a Python library designed for interacting with RabbitMQ. It is built to be consistent, stable, and thread-safe. It maintains 100% test coverage and requires Python 3.11 or higher.
Install AMQPStorm with management module support
mainTo use the management module features (such as interacting with the RabbitMQ Management API), you must install
amqpstormwith themanagementextra. This ensures the requiredrequestslibrary is also installed.Run the following command:
pip install amqpstorm[management]Install AMQPStorm via pip
mainYou can install the core AMQPStorm library using
pip. If you require the management API features, install the library with the[management]extra.# Install the core library pip install amqpstorm # Install with management dependencies pip install amqpstorm[management]Install AMQPStorm
mainAMQPStorm is a thread-safe Python 3 RabbitMQ client and management library. It supports Python 3.11 and newer. You can install it via pip.
pip install AMQPStormImplement a simple RPC server with AMQPStorm
mainTo implement a Remote Procedure Call (RPC) server using AMQPStorm, you can use a pattern where the server listens on a specific queue, processes incoming messages, and sends a response back to the
reply_toqueue specified in the message properties.In a typical RPC implementation:
- The server consumes messages from a dedicated request queue.
- For each message, the server performs the requested logic.
- The server publishes the result to the queue name provided in the
reply_toproperty of the incoming message. - The server uses the
correlation_idfrom the request to ensure the client can match the response to the original request.
import amqpstorm def on_request(channel, method, properties, body): print(f'Received request: {body.decode()} ') # Perform some work response = body.decode().upper() # Send the response back to the reply_to queue channel.basic_publish( exchange='', routing_key=properties.reply_to, body=response.encode(), correlation_id=properties.correlation_id ) # Acknowledge the message channel.basic_ack(delivery_tag=method.delivery_tag) def main(): connection = amqpstorm.Connection({ 'host': 'localhost', 'port': 5672, 'login': 'guest', 'password': 'guest' }) channel = connection.channel() # Declare the queue for requests channel.queue_declare(queue='rpc_queue') # Set up the consumer channel.basic_consume(queue='rpc_queue', on_message_callback=on_request) print('RPC Server is running. To exit press CTRL+C') channel.start_consuming() if __name__ == '__main__': main()Basic AMQP message publishing example
mainTo publish a message to RabbitMQ, use
amqpstorm.Connectionto establish a connection, create a channel usingconnection.channel(), declare a queue, and then useamqpstorm.Message.create()to prepare and publish the message.import amqpstorm with amqpstorm.Connection('rmq.eandersson.net', 'guest', 'guest') as connection: with connection.channel() as channel: channel.queue.declare('fruits') message = amqpstorm.Message.create( channel, body='Hello RabbitMQ!', properties={ 'content_type': 'text/plain' }) message.publish('fruits')Implement a Flask RPC Client using AMQPStorm
mainYou can implement a Remote Procedure Call (RPC) client within a Flask application by using a threaded approach to handle AMQP communication. This allows the Flask web server to remain responsive while waiting for responses from an AMQP-based RPC server.
In this pattern, the client typically:
- Creates an
AMQPConnection. - Uses a thread or a non-blocking mechanism to manage the request-response lifecycle.
- Sends a message to a specific queue and waits for a response on a callback queue.
# Note: The actual implementation is contained in examples/flask_threaded_rpc_client.py # This pattern involves integrating AMQPStorm within Flask routes or background threads.- Creates an
Implement a simple AMQP publisher
mainTo publish messages to an AMQP broker using
amqpstorm, you need to establish a connection, open a channel, declare an exchange, and then use thebasic_publishmethod. This pattern is used for sending data to specific routing keys or exchanges in a standard AMQP workflow.import amqpstorm # Establish connection and open a channel with amqpstorm.Connection('localhost', username='guest', password='guest') as connection: with connection.channel() as channel: # Declare an exchange (e.g., a direct exchange named 'my_exchange') channel.exchange_declare(exchange='my_exchange', exchange_type='direct') # Publish a message to the exchange with a specific routing key channel.basic_publish( exchange='my_exchange', routing_key='my_routing_key', body='Hello, AMQP!' )Implement a simple AMQP consumer
mainTo consume messages from an AMQP queue using
amqpstorm, you need to establish a connection, create a channel, and then use theconsumemethod on the channel. Theconsumemethod accepts a callback function that is invoked whenever a message is received.Key steps:
- Create an
AMQPConnectionwith your broker credentials. - Open an
AMQPChannelfrom the connection. - Call
channel.consume(queue_name, callback)to start listening for messages. - The callback function receives the
AMQPMessageobject, which contains thebody(the message payload) and other metadata.
import amqpstorm def callback(message): print(f'Received message: {message.body}') message.ack() connection = amqpstorm.Connection(host='localhost', username='guest', password='guest') connection.connect() channel = connection.channel() channel.queue.declare(name='test_queue') # Start consuming from the queue channel.consume('test_queue', callback) # Keep the script running to listen for messages connection.process_events()- Create an
Create a RabbitMQ User
mainYou can programmatically create a RabbitMQ user using the management module. This requires the
requestslibrary to interact with the RabbitMQ Management HTTP API.Refer to the example below for the implementation pattern.
# Example implementation from examples/management/create_user.py # Note: This requires amqpstorm[management] to be installedImplement a robust AMQP consumer
mainTo build a resilient AMQP consumer that can handle connection interruptions and unexpected errors, you should implement a loop that manages the connection and channel lifecycle. A robust pattern involves:
- Connection Management: Wrapping the
AMQPStorm.Connectioninstantiation and theconnection.start()call in a retry loop. - Channel Management: Creating the channel within the connection context.
- Consumer Loop: Using
channel.consume()to start receiving messages. - Error Handling: Catching exceptions within the message processing logic to prevent the entire consumer from crashing, and catching connection-level exceptions to trigger a reconnection attempt.
- Graceful Shutdown: Using
try...finallyblocks to ensureconnection.stop()is called, which closes the connection and cleans up resources.
import AMQPStorm import time def run_consumer(): while True: connection = None try: # 1. Establish connection connection = AMQPStorm.Connection( host='localhost', login='guest', password='guest' ) with connection: channel = connection.channel() # 2. Setup queue and consumer channel.queue_declare(queue='robust_queue') print('[*] Waiting for messages. To exit press CTRL+C') # 3. Consume messages for method, properties, body in channel.consume('robust_queue'): try: print(f' [x] Received {body!r}') # Simulate work time.sleep(1) # 4. Acknowledge message channel.basic_ack(delivery_tag=method.delivery_tag) except Exception as e: print(f' [!] Error processing message: {e}') # 5. Nack message on processing error channel.basic_nack(delivery_tag=method.delivery_tag, requeue=True) except (AMQPStorm.exceptions.AMQPError, ConnectionError) as e: print(f' [!] Connection error: {e}. Retrying in 5 seconds...') time.sleep(5) except KeyboardInterrupt: print(' [!] Stopping consumer...') break finally: if connection: connection.stop() if __name__ == '__main__': run_consumer()- Connection Management: Wrapping the
Establish an SSL connection using an SSLContext
mainTo establish a secure SSL connection with an AMQP broker using
amqpstorm, you can provide a pre-configuredssl.SSLContextobject. This is useful when you need fine-grained control over certificate validation, loading CA certificates, or configuring specific SSL/TLS settings. Pass the context object to thessl_contextparameter when initializing theAMQPConnection.import ssl from amqpstorm import AMQPConnection # Create an SSL context ssl_context = ssl.create_default_context() # Optionally load specific CA certificates or configure settings # ssl_context.load_verify_locations(cafile='path/to/ca_certificate.pem') # Connect using the SSL context with AMQPConnection(host='your-broker-host', port=5671, ssl_context=ssl_context) as connection: channel = connection.channel() # Perform AMQP operations print("Connected securely via SSL")