Skip to main content

🐰 RabbitMQ AsyncIO Consumer/Producer

Python 3.13+

Простая в использовании библиотека для работы с 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 shutdown
  • stop() - Останавливает 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)

Source distribution for autosell-rmq 0.1.4
File Size Uploaded Provenance
autosell_rmq-0.1.4.tar.gz 10.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for autosell-rmq 0.1.4
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page