Skip to main content

No project description provided

Project description

🐰 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autosell_rmq-0.1.2.tar.gz (9.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autosell_rmq-0.1.2-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file autosell_rmq-0.1.2.tar.gz.

File metadata

  • Download URL: autosell_rmq-0.1.2.tar.gz
  • Upload date:
  • Size: 9.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.13.5 Linux/6.11.0-1018-azure

File hashes

Hashes for autosell_rmq-0.1.2.tar.gz
Algorithm Hash digest
SHA256 6e718a4a29d44aece9842df35528724789f55c0cdc1beb4406b94087d11b8fe1
MD5 02cffa6ee603e54dd01a0c709c7bd224
BLAKE2b-256 d1e7650c2b89a36d0a14649d1ee366438bc58ca31ae30c2e2162dbb1422f4340

See more details on using hashes here.

File details

Details for the file autosell_rmq-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: autosell_rmq-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.13.5 Linux/6.11.0-1018-azure

File hashes

Hashes for autosell_rmq-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 af28e470471d8f539001e99f291f0abc4a1fb33bfb1a0a4805288eeb9637364b
MD5 3270756d2760b691b07fd20dffa64ca5
BLAKE2b-256 8229ecc31119d5a94963c12f0fd254e9d109e0a53a70416a4659bb6b34235f26

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page