🐰 RabbitMQ AsyncIO Consumer/Producer
Простая в использовании библиотека для работы с RabbitMQ в асинхронном режиме на Python. Поддерживает идемпотентность, Dead Letter Queue (DLQ), автоматические ответы и graceful shutdown.
🚀 Особенности
- 🔄 Асинхронная обработка сообщений с использованием
aio_pika - 🔁 Автоматические ответы по
reply_toсcorrelation_id - ☠️ Dead Letter Queue (DLQ) для обработки ошибок
- 🔂 Идемпотентность - защита от повторной обработки сообщений
- 🔄 Retry механизм с настраиваемым количеством попыток
- 🛡️ Graceful shutdown с обработкой сигналов
- 📊 Подробное логирование всех операций
- 🎯 Простой API для быстрого старта
📦 Установка
pip install autosell-rmq
🏃♂️ Быстрый старт
Consumer
import asyncio
from autosell_rmq import RabbitMQConsumer
async def message_handler(message_data: dict) -> dict:
"""Ваш обработчик сообщений"""
print(f"Получено: {message_data}")
# Ваша бизнес-логика здесь
result = {"processed": True, "data": message_data}
return result
async def main():
# Создаем consumer
consumer = RabbitMQConsumer(
connection_url="amqp://guest:guest@localhost/",
queue_name="my_queue",
dlq_name="my_queue_dlq"
)
# Устанавливаем обработчик
consumer.set_message_handler(message_handler)
try:
# Запускаем (работает до Ctrl+C)
await consumer.run_forever()
finally:
await consumer.close()
if __name__ == "__main__":
asyncio.run(main())
Producer
import asyncio
from autosell_rmq import RabbitMQProducer
async def main():
producer = RabbitMQProducer("amqp://guest:guest@localhost/")
try:
# Отправляем сообщение и ждем ответ
response = await producer.send_message(
queue_name="my_queue",
message_data={"text": "Привет, мир!", "user_id": 123}
)
print(f"Ответ: {response}")
# Вывод: {"success": True, "data": {...}, "correlation_id": "..."}
# Отправляем без ожидания ответа
correlation_id = await producer.send_fire_and_forget(
queue_name="my_queue",
message_data={"type": "notification", "text": "Уведомление"}
)
print(f"Отправлено: {correlation_id}")
finally:
await producer.close()
if __name__ == "__main__":
asyncio.run(main())
📚 Подробная документация
RabbitMQConsumer
Параметры конструктора
consumer = RabbitMQConsumer(
connection_url="amqp://guest:guest@localhost/", # URL подключения к RabbitMQ
queue_name="main_queue", # Имя основной очереди
dlq_name="dlq_queue", # Имя Dead Letter Queue
max_retries=3 # Максимальное количество повторов
)
Методы
set_message_handler(handler)- Устанавливает обработчик сообщенийstart_consuming()- Запускает обработку сообщенийrun_forever()- Запускает consumer с graceful shutdownstop()- Останавливает consumer программноclose()- Закрывает соединение
RabbitMQProducer
Параметры конструктора
producer = RabbitMQProducer(
connection_url="amqp://guest:guest@localhost/" # URL подключения к RabbitMQ
)
Методы
send_message(queue_name, message_data, wait_for_response=True, timeout=30.0)- Отправляет сообщениеsend_fire_and_forget(queue_name, message_data)- Отправляет без ожидания ответаclose()- Закрывает соединение
🔧 Расширенные примеры
Настройка обработчика с ошибками
async def robust_handler(message_data: dict) -> dict:
try:
# Ваша бизнес-логика
if message_data.get("simulate_error"):
raise ValueError("Имитация ошибки")
# Обработка данных
result = process_business_logic(message_data)
return {
"success": True,
"result": result,
"processed_at": datetime.now().isoformat()
}
except ValueError as e:
# Логируем ошибку - сообщение попадет в DLQ
logging.error(f"Ошибка обработки: {e}")
raise # Перебрасываем для отправки в DLQ
except Exception as e:
# Неожиданная ошибка
logging.error(f"Неожиданная ошибка: {e}")
raise
Использование с пулом соединений
import asyncio
from contextlib import asynccontextmanager
@asynccontextmanager
async def consumer_context(queue_name: str):
consumer = RabbitMQConsumer(queue_name=queue_name)
consumer.set_message_handler(my_handler)
try:
await consumer.start_consuming()
yield consumer
finally:
await consumer.close()
async def main():
async with consumer_context("orders_queue") as consumer:
# Consumer работает в контексте
await consumer.run_forever()
Batch обработка
async def send_batch_messages():
producer = RabbitMQProducer()
try:
# Отправляем несколько сообщений параллельно
tasks = []
for i in range(10):
task = producer.send_message(
"batch_queue",
{"batch_id": "batch_001", "item": i, "data": f"item_{i}"}
)
tasks.append(task)
# Ждем все ответы
responses = await asyncio.gather(*tasks, return_exceptions=True)
for i, response in enumerate(responses):
if isinstance(response, Exception):
print(f"Ошибка в сообщении {i}: {response}")
else:
print(f"Ответ {i}: {response}")
finally:
await producer.close()
🔄 Идемпотентность
Библиотека автоматически обеспечивает идемпотентность обработки сообщений на основе correlation_id:
# Первая отправка
response1 = await producer.send_message(
"test_queue",
{"data": "test"},
correlation_id="unique-id-123"
)
# Повторная отправка с тем же correlation_id
# Вернет тот же результат без повторной обработки
response2 = await producer.send_message(
"test_queue",
{"data": "different data"},
correlation_id="unique-id-123"
)
# response1 == response2
☠️ Dead Letter Queue (DLQ)
Сообщения автоматически попадают в DLQ в следующих случаях:
- Превышено максимальное количество попыток обработки
- Ошибка парсинга JSON
- Необработанное исключение в обработчике
- Отсутствие обработчика сообщений
Структура сообщения в DLQ:
{
"original_body": "...",
"reason": "Превышено максимальное количество попыток: ...",
"failed_at": "2024-01-15T10:30:00",
"correlation_id": "...",
"original_queue": "main_queue"
}
⚙️ Конфигурация
Переменные окружения
export RABBITMQ_URL="amqp://user:pass@localhost:5672/vhost"
export QUEUE_NAME="my_app_queue"
export DLQ_NAME="my_app_dlq"
export MAX_RETRIES="5"
Конфигурация через код
import os
consumer = RabbitMQConsumer(
connection_url=os.getenv("RABBITMQ_URL", "amqp://guest:guest@localhost/"),
queue_name=os.getenv("QUEUE_NAME", "default_queue"),
dlq_name=os.getenv("DLQ_NAME", "default_dlq"),
max_retries=int(os.getenv("MAX_RETRIES", "3"))
)
📊 Мониторинг и логирование
Библиотека предоставляет подробное логирование:
import logging
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Логи будут содержать:
# - Подключение к RabbitMQ
# - Обработка сообщений
# - Отправка ответов
# - Ошибки и перемещение в DLQ
# - Статистика идемпотентности
📝 Требования
- Python >=3.13,<4
- aio-pika
- RabbitMQ Server
📈 Changelog
v1.0.0
- ✨ Первый релиз
- 🔄 Базовая функциональность Consumer/Producer
- 🔂 Поддержка идемпотентности
- ☠️ Dead Letter Queue
- 🛡️ Graceful shutdown
Создано с ❤️ для разработчиков autosell.kz
Metadata
Release files for autosell-rmq 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| autosell_rmq-0.1.4.tar.gz | 10.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| autosell_rmq-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.0 kB
Release files / autosell_rmq-0.1.4.tar.gz
| Download URL | autosell_rmq-0.1.4.tar.gz |
|---|---|
| Size | 10.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b172c854be5e93b5a01796b76391152bacba76bc7ee082a7d714ce0bd68897d
|
|
BLAKE2b-256 checksum How to use checksums |
e3b9e44e1030f41c65b3cf30e30bac22cb1a90a3517843ff80309a977082e1de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.3.4 CPython/3.13.13 Linux/6.17.0-1010-azure
|
Release files / autosell_rmq-0.1.4-py3-none-any.whl
| Download URL | autosell_rmq-0.1.4-py3-none-any.whl |
|---|---|
| Size | 9.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4b480407965c044e51bc3c9ffc01f0ca016bf394187e9b52bcfaf288927fcb1f
|
|
BLAKE2b-256 checksum How to use checksums |
bba24e166fe76e9d292798989bad8894e82f1e397895213a779a483fb20ba11e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.3.4 CPython/3.13.13 Linux/6.17.0-1010-azure
|
Security for autosell-rmq 0.1.4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.