Integración de Eventos SQL con RabbitMQ para Procesos Asíncronos

·

4 min read

En sistemas modernos, la capacidad de reaccionar ante eventos en tiempo real es crucial. Integrar bases de datos como PostgreSQL con sistemas de mensajería como RabbitMQ permite procesar eventos de manera eficiente y desacoplada. Este documento explora cómo llevar eventos SQL (como INSERT, UPDATE, DELETE) a RabbitMQ y detalla los elementos clave de RabbitMQ aplicados a un caso práctico. También referenciamos el artículo publicado previamente en Integración de PostgreSQL con RabbitMQ mediante pg_amqp.

Arquitectura General

Conceptos Clave de RabbitMQ

Para entender la integración, primero debemos repasar los elementos principales de RabbitMQ:

  • Exchange: Punto de entrada para mensajes. Los exchanges determinan a qué colas se envían los mensajes basándose en las claves de enrutamiento.

  • Queue: Almacén de mensajes. Las colas mantienen los mensajes hasta que un consumidor los procesa.

  • Message: El dato que viaja por RabbitMQ. Contiene la información necesaria para procesar un evento.

  • Consumer: Suscriptor que procesa los mensajes desde una cola.

Estos componentes trabajan juntos para manejar eventos de manera eficiente y desacoplada.

Caso Práctico: Reactivar una Página HTML tras un Evento SQL

Objetivo: Cuando se actualiza un producto en PostgreSQL, se genera un evento que desencadena la regeneración del HTML de la página del producto en un CDN.

Flujo Propuesto:

  1. Evento SQL: Ocurre una actualización en la tabla products.

  2. Trigger PostgreSQL: Publica un mensaje en RabbitMQ con detalles del evento.

  3. Exchange RabbitMQ: Recibe el mensaje y lo distribuye a una cola.

  4. Queue RabbitMQ: Almacena el mensaje hasta que un consumidor lo procese.

  5. Consumer: Reconstruye la página HTML y la publica en el CDN.

Tabla de Equivalencias

Para clarificar la relación entre los conceptos de tu flujo y los elementos de RabbitMQ, aquí presentamos una tabla:

Concepto en tu FlujoElemento en RabbitMQDescripción
Sucede algo (products.update)ExchangeDistribuye el mensaje del evento al lugar correcto (colas) basado en una clave.
Datos del evento (payload)MessageContiene entity, entity_id, datetime, etc.
Se debe hacer algo (rebuild HTML)QueueAlmacena los mensajes hasta que un consumidor los procese.
Alguien lo hace (suscriptor)ConsumerEl proceso o servicio que recibe y ejecuta la acción (reconstruir la página HTML).

Implementación Paso a Paso

1. Configuración de RabbitMQ

Crear un Exchange y una Cola:

# Crear un exchange de tipo 'direct'
rabbitmqadmin declare exchange name=product.events type=direct

# Crear una cola para los eventos de regeneración de HTML
rabbitmqadmin declare queue name=html.rebuild durable=true

# Enlazar el exchange con la cola
rabbitmqadmin declare binding source=product.events destination=html.rebuild routing_key=products.update

Explicación:

  • Exchange product.events: Recibe eventos relacionados con productos.

  • Queue html.rebuild: Almacena mensajes para la regeneración de páginas HTML.

  • Routing Key products.update: Filtra mensajes relacionados con actualizaciones de productos.

2. Configuración en PostgreSQL

Crear la Tabla de Productos:

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name TEXT,
    description TEXT,
    price NUMERIC,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Agregar un Trigger para Publicar Eventos:

Usando la extensión pg_amqp como se detalla en nuestro artículo relacionado, configuramos un trigger que envíe eventos a RabbitMQ.

Crear la Función del Trigger:
CREATE OR REPLACE FUNCTION notify_product_update()
RETURNS TRIGGER AS $$
DECLARE
    payload JSON;
BEGIN
    -- Crear el mensaje en formato JSON
    payload = json_build_object(
        'entity', 'product',
        'entity_id', NEW.id,
        'datetime', CURRENT_TIMESTAMP,
        'action', TG_OP
    );

    -- Publicar el mensaje en RabbitMQ
    PERFORM amqp.publish('amqp://guest:guest@localhost:5672/',
                         'product.events', 'products.update', payload::TEXT);

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Crear el Trigger:
CREATE TRIGGER product_update_trigger
AFTER UPDATE ON products
FOR EACH ROW
EXECUTE FUNCTION notify_product_update();

3. Consumidor RabbitMQ

Un consumidor procesa los mensajes de la cola html.rebuild y ejecuta la lógica necesaria para reconstruir la página HTML.

Ejemplo de Consumidor en Python:

import pika
import json

def rebuild_html(ch, method, properties, body):
    message = json.loads(body)
    entity_id = message['entity_id']

    # Lógica para regenerar la página HTML
    print(f"Rebuilding HTML for product {entity_id}")

    # Acknowledge message
    ch.basic_ack(delivery_tag=method.delivery_tag)

# Conexión a RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# Escuchar mensajes de la cola
channel.basic_consume(queue='html.rebuild', on_message_callback=rebuild_html)
print('Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

4. Flujo Completo

  1. Un cliente o sistema actualiza un producto:

     UPDATE products SET price = 1500 WHERE id = 1;
    
  2. El trigger product_update_trigger publica un mensaje en RabbitMQ:

     {
         "entity": "product",
         "entity_id": 1,
         "datetime": "2025-01-07T12:00:00Z",
         "action": "UPDATE"
     }
    
  3. RabbitMQ distribuye el mensaje a la cola html.rebuild.

  4. El consumidor procesa el mensaje y reconstruye la página HTML.

Beneficios del Enfoque

  • Desacoplamiento: La base de datos y el CDN están desacoplados mediante RabbitMQ.

  • Escalabilidad: Los consumidores pueden escalar horizontalmente para manejar mayor carga.

  • Resiliencia: Los mensajes persisten en RabbitMQ hasta que sean procesados exitosamente.

Conclusión

La integración de eventos SQL con RabbitMQ permite crear flujos de trabajo eficientes y desacoplados. Usar herramientas como pg_amqp simplifica este proceso al conectar directamente PostgreSQL con RabbitMQ. Este enfoque es ideal para sistemas modernos que requieren reaccionar rápidamente a eventos en tiempo real.