SAP CAP + RabbitMQ: Cómo hacer que tu backend hable con colas de mensajes

¿Desacoplar CAP? ¿Que en vez de peticiones directas, se manden mensajitos por una cola y así evitar cuellos de botella? Pues hoy te voy a contar cómo integrar SAP CAP con RabbitMQ, una de las soluciones de mensajería más usadas en el mundillo.
¿Qué vamos a montar?
- Un proyecto SAP CAP (Node.js)
- Un servidor RabbitMQ local o en Docker
- Una integración para enviar mensajes desde CAP a una cola en RabbitMQ
Opcional: un consumer para leer esos mensajes (porque está guay ver qué se recibe).
Requisitos previos
- Node.js instalado
- Docker (para RabbitMQ)
- Proyecto CAP creado (cds init sap-cap-rabbitmq)
- Cliente AMQP para Node.js (usaremos amqplib)
npm install amqplib
Levantando RabbitMQ con Docker
Si no tienes un RabbitMQ montado, en 5 segundos lo tienes:
docker run -d --hostname my-rabbit --name some-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
La consola de administración estará en: http://localhost:15672
Usuario: guest / Contraseña: guest
Integrando SAP CAP con RabbitMQ
Vamos a crear un servicio en CAP que envíe mensajes a RabbitMQ.
- Crea un módulo JS para la conexión
/srv/cat-service.js
const cds = require('@sap/cds');
const amqp = require('amqplib');
module.exports = cds.service.impl(async function () {
this.on('sendMessage', async (req) => {
const { queue, message } = req.data;
try {
// Conectar a RabbitMQ
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
await channel.assertQueue(queue, { durable: false });
console.log(`
Enviando mensaje a ${queue}...`);
// Enviar el mensaje a la cola una vez
channel.sendToQueue(queue, Buffer.from(message));
console.log(`
Mensaje enviado a ${queue}: ${message}`);
// Cerrar conexión
await channel.close();
await connection.close();
console.log('
Conexión cerrada');
return `Mensaje enviado a ${queue}`;
} catch (error) {
console.error('
Error enviando mensaje:', error);
return 'Error al enviar el mensaje';
}
});
});
- Define la acción en tu CDS
/srv/cat-service.cds
using myapp from '../db/schema';
service MensajeriaService {
entity Mensajes as projection on myapp.Mensajes;
action sendMessage(queue: String, message: String) returns String;
}
- Define la entidad mensaje
namespace myapp;
entity Mensajes {
key ID : UUID;
queue : String;
message: String;
}
- Testea enviando un POST al servicio
curl -X POST http://localhost:4004/catalog/sendToQueue -H "Content-Type: application/json" -d '{"text": "¡Hola Rabbit!"}'
Verifica el mensaje en la consola de RabbitMQ
Entra en http://localhost:15672, busca la cola my_queue y verás tu mensaje esperando.
Opcional: Monta otro servicio para consumir de la cola de RabbitMQ, aquí te dejo un código de ejemplo.
const cds = require('@sap/cds');
const amqp = require('amqplib');
module.exports = cds.service.impl(async function () {
const queue = 'myQueue'; // Nombre de la cola en RabbitMQ
async function consumeMessages() {
try {
// Conectar a RabbitMQ
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
await channel.assertQueue(queue, { durable: false });
console.log(`
[SAP CAP] Esperando mensajes en la cola: ${queue}...`);
// Consumir mensajes de la cola
channel.consume(queue, async (msg) => {
if (msg !== null) {
const messageContent = msg.content.toString();
console.log(`
Mensaje recibido: ${messageContent}`);
// Aquí puedes procesar el mensaje, por ejemplo, guardarlo en la base de datos
const db = await cds.connect.to('db');
await db.run(INSERT.into('Mensajes').entries({
ID: cds.utils.uuid(),
queue: queue,
message: messageContent
}));
// Confirmar procesamiento del mensaje
channel.ack(msg);
}
});
} catch (error) {
console.error('
Error en el consumidor de RabbitMQ:', error);
}
}
// Ejecutar el consumidor cuando arranque el servicio CAP
consumeMessages();
});
Conclusión
Y listo. Ya tienes SAP CAP enviando mensajes a RabbitMQ. Esto viene genial para desacoplar procesos pesados o notificar a otros sistemas.