Brokers
Un bridge publica los eventos del ledger de una app en un bus de mensajes que ya tienes: NATS JetStream, RabbitMQ, Kafka o SQS. Es la opción cuando varios consumidores leen los mismos eventos, cuando quieres la retención y el fan-out del bus, o cuando tu equipo ya opera uno. Cada mensaje lleva el mismo sobre que un webhook.
Esos cuatro son los únicos brokers que el motor trae. Para otros destinos (Pusher, un archivo en S3, un bot), un conector tuyo consume por webhook, stream o bridge y hace el resto.
Quién lo configura
Sección titulada «Quién lo configura»Un operador, en el panel del motor, en la ficha de tu app (sección Bridges). La API /v1 no
tiene rutas de bridges: tu app no los crea ni los ve. Pídele al operador:
- Que agregue los hosts del broker a los destinos permitidos de la app (los mismos de los webhooks): los servidores que configuras y los que anuncia el broker (los otros nodos de un cluster de NATS, los listeners anunciados de Kafka).
- Que cree el bridge con su configuración y su secreto, y lo pruebe («Probar» conecta y comprueba el destino sin publicar nada).
Crear, editar, cambiar el secreto, pausar, borrar y reenviar es de un superadmin; ver, probar y revisar la DLQ, de cualquier operador. El secreto se guarda sellado y nunca vuelve a mostrarse.
| Campo | Qué es |
|---|---|
nombre |
Único dentro de la app. |
tipo |
nats, rabbitmq, kafka o sqs. |
config |
Lo de cada broker (abajo). Sin contraseñas: van en el secreto. |
secreto |
La contraseña, el token o la clave secreta. |
instancias |
Vacío: todas las de la app. |
tipos |
Tipos de evento. Vacío: todos. |
Un bridge nuevo publica lo que llegue desde ahora, como una suscripción nueva: lo anterior no se manda (para eso está el replay).
Cada broker
Sección titulada «Cada broker»| Broker | config |
Secreto | Dónde publica |
|---|---|---|---|
| NATS JetStream | servidores (nats://host:4222 o tls://…, hasta 10), subject (prefijo; por omisión motor), stream (opcional, para «Probar») |
Opcional: la contraseña de usuario, o un token si no hay usuario |
Subject <subject>.<instance_id>.<type> |
| RabbitMQ | url (amqp://host:5672/vhost o amqps://…, sin usuario), exchange (por omisión motor.eventos), usuario |
Obligatorio: la contraseña | Exchange topic, routing key <instance_id>.<type>, mensaje persistente y mandatory |
| Kafka | servidores (host:9092), topic, sasl (ninguno, plain, scram-sha-256 o scram-sha-512), tls, usuario |
La contraseña de SASL (obligatoria con SASL) | El topic, con clave = instance_id |
| SQS | cola_url, region, endpoint (opcional, un compatible con SQS), usuario (el access key ID) |
Obligatorio: el secret access key | La cola; en una .fifo, grupo = instance_id |
Ejemplos de suscripción del lado del consumidor:
- NATS:
motor.>(todo),motor.*.message.received(un tipo de todas las instancias) omotor.INSTANCIA_ID.>(una instancia). - RabbitMQ: enlaza tu cola con
#(todo),*.message.receivedoINSTANCIA_ID.#.
El mensaje
Sección titulada «El mensaje»El cuerpo es el sobre del evento en JSON, idéntico al de un webhook. Los metadatos van en los encabezados o atributos de cada broker, para filtrar y deduplicar sin parsear el cuerpo:
| Dato | NATS (headers) | RabbitMQ (propiedades y headers) | Kafka (headers) | SQS (atributos) |
|---|---|---|---|---|
event_id |
Nats-Msg-Id y Motor-Event-Id |
message_id y motor-event-id |
motor-event-id |
motor-event-id (y MessageDeduplicationId en .fifo) |
instance_id |
Motor-Instance-Id |
motor-instance-id |
La clave del mensaje | motor-instance-id (y MessageGroupId en .fifo) |
type |
Motor-Event-Type |
type |
motor-event-type |
motor-event-type |
seq |
Motor-Seq |
motor-seq |
motor-seq |
motor-seq (Number) |
| Formato | Content-Type: application/json |
content_type: application/json |
content-type: application/json |
— |
El checkpoint y la entrega
Sección titulada «El checkpoint y la entrega»Cada bridge lleva un checkpoint por instancia: el último seq que el broker confirmó. El motor
publica los eventos siguientes en orden de seq y avanza el checkpoint solo con el ACK del
broker (el PubAck de JetStream, el publisher confirm de RabbitMQ, el ACK de Kafka, la
respuesta de SQS).
- Al menos una vez. Si el motor se cae entre el ACK y el avance del checkpoint, el mismo evento
sale otra vez con el mismo
event_id. Deduplica porevent_id, igual que con un webhook. - Sin copias en memoria. Un mensaje sin ACK es un error y se vuelve a leer del ledger: el motor no guarda nada en un buffer de reconexión.
- Lo que dice el alcance vigente. Cada evento se relee del ledger justo antes de publicarlo: si su contenido venció, sale redactado; si cambias las instancias o los tipos del bridge, vale lo nuevo.
Los errores y los reintentos
Sección titulada «Los errores y los reintentos»| Error | Qué hace el motor |
|---|---|
Sin conexión, timeout o destino_inexistente |
El evento en cabeza de esa instancia reintenta con backoff: 1 s, 5 s, 30 s, 2 min, 10 min y luego cada hora. Los eventos siguientes de esa instancia esperan. |
El broker rechaza ese mensaje (rechazado_por_broker: un tamaño, un nack) |
Va a la DLQ enseguida y el checkpoint sigue con el siguiente. |
Pasa la vida máxima reintentando (72 h; bridges.horas_vida, de 1 a 720) |
Va a la DLQ y el checkpoint sigue. |
El broker rechaza la credencial (credencial_rechazada) |
El bridge queda suspendido. Al reactivarlo, sigue desde su checkpoint. |
Cada intento espera la conexión y el ACK hasta 10 s (bridges.timeout_segundos). Un broker caído
no frena a los demás bridges ni a los webhooks: tienen su propio trabajo.
La DLQ de un bridge la ve el operador en el panel. Desde ahí reenvía toda la DLQ, algunas entregas o
un rango de hasta 10 000 seq de una instancia; lo reenviado sale fuera del orden normal y con
sus reintentos. Nada de eso vuelve a mandar algo a WhatsApp.
| Estado del bridge | Qué significa |
|---|---|
activo |
Publica. |
pausado |
No publica; el checkpoint espera. No se pierde nada. |
suspendido |
El broker rechazó la credencial. Lo reactiva un operador. |
eliminado |
Ya no publica. |
El panel muestra además el estado de la conexión (sin_probar, conectado o caido), el último
error real del broker (saneado, sin el secreto), el atraso (eventos que el broker todavía no
confirmó), las instancias que están reintentando y el tamaño de la DLQ.
El orden
Sección titulada «El orden»| Broker | Orden por instancia | Deduplicación del lado del broker |
|---|---|---|
| NATS JetStream | Sí: el motor publica en orden y espera cada ACK. | Sí, con Nats-Msg-Id dentro de la ventana de duplicados del stream. |
| RabbitMQ | Sí, en cada cola que recibe los mensajes. | No: deduplica por message_id. |
| Kafka | Sí: la clave es el instance_id, así que una instancia va siempre a la misma partición. |
No: deduplica por motor-event-id. |
SQS .fifo |
Sí: MessageGroupId es el instance_id. |
Sí, con MessageDeduplicationId (5 minutos, la ventana de SQS). |
| SQS estándar | No: SQS no garantiza el orden. | No. Ordena por motor-seq y deduplica por motor-event-id en tu consumidor. |
Entre instancias distintas no hay orden en ningún broker. Lo reenviado desde la DLQ o por un rango
sale fuera del orden normal: usa seq para ubicarlo.