Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt

Use this file to discover all available pages before exploring further.

Esta página fue traducida automáticamente. Si encuentra errores o tiene sugerencias, contáctenos.
Rhombus utiliza STOMP 1.2 (Streaming Text Oriented Messaging Protocol) sobre WebSocket para la entrega de eventos en tiempo real. Esta página es una referencia del protocolo para desarrolladores que necesitan entender o implementar el framing de STOMP a bajo nivel.

¿Qué es STOMP?

STOMP es un protocolo de mensajería simple y basado en texto que proporciona un formato de cable interoperable para los brokers de mensajes. Define un pequeño conjunto de comandos (frames) para conectar, suscribirse, enviar y desconectar. Rhombus usa STOMP porque proporciona mensajería pub/sub estructurada sobre un transporte WebSocket estándar.

Formato del frame

Cada frame STOMP sigue esta estructura:
COMMAND\n
header-key:header-value\n
header-key:header-value\n
\n
body (optional)
\x00
  • COMMAND: Una sola palabra que identifica el tipo de frame (por ejemplo, CONNECT, MESSAGE)
  • Headers: Cero o más pares key:value, uno por línea
  • Línea vacía: Separa los headers del cuerpo
  • Cuerpo: Carga útil opcional (típicamente JSON para frames MESSAGE)
  • Byte nulo (\x00): Termina cada frame

Ejemplo: frame CONNECT sin procesar

CONNECT\n
accept-version:1.2\n
heart-beat:10000,10000\n
\n
\x00

Frames del cliente al servidor

CONNECT

Inicia la sesión STOMP después de que la conexión WebSocket esté abierta.
HeaderRequeridoValorDescripción
accept-version1.2Versión del protocolo STOMP
heart-beat10000,10000Intervalo de envío del cliente y el intervalo deseado de recepción (ms)
CONNECT
accept-version:1.2
heart-beat:10000,10000

\x00

SUBSCRIBE

Se suscribe a un tópico de destino para recibir mensajes.
HeaderRequeridoValorDescripción
idsub-0Identificador de suscripción definido por el cliente
destination/topic/change/{orgUuid}Ruta del tópico al cual suscribirse
SUBSCRIBE
id:sub-0
destination:/topic/change/a1b2c3d4-e5f6-7890-abcd-ef1234567890

\x00
El id de la suscripción es definido por el cliente. Usa cualquier cadena única. Si creas múltiples suscripciones, cada una debe tener un id distinto.

DISCONNECT

Indica una desconexión limpia e intencional.
DISCONNECT

\x00
No se requieren headers ni cuerpo. Después de enviar DISCONNECT, cierra la conexión WebSocket subyacente.

Frames del servidor al cliente

CONNECTED

Enviado por el servidor en respuesta a un CONNECT exitoso.
HeaderValorDescripción
version1.2Versión STOMP negociada
heart-beat10000,10000Intervalos de heartbeat de envío/recepción del servidor
CONNECTED
version:1.2
heart-beat:10000,10000

\x00

MESSAGE

Entrega un evento desde un tópico suscrito.
HeaderValorDescripción
destination/topic/change/{orgUuid}El tópico al que pertenece este mensaje
message-idGenerado por el servidorIdentificador único del mensaje
subscriptionsub-0Coincide con el id de la suscripción
MESSAGE
destination:/topic/change/a1b2c3d4-e5f6-7890-abcd-ef1234567890
message-id:msg-001
subscription:sub-0

{"entity":"POLICY_ALERT","entityUuid":"x1y2z3","type":"CREATE","timestampMs":1711843200000}
\x00
El cuerpo siempre es un objeto JSON que contiene la carga útil del evento.

Heartbeats

Los heartbeats mantienen viva la conexión y detectan fallos. Se negocian durante el intercambio CONNECT/CONNECTED.

Formato

Un heartbeat es un único carácter de salto de línea:
\n
Sin comando, sin headers, sin terminador nulo. Solo \n.

Negociación

El header heart-beat usa el formato cx,cy donde:
  • cx = intervalo mínimo (ms) al que el cliente puede enviar heartbeats
  • cy = intervalo deseado (ms) al que el cliente quiere recibir heartbeats
El servidor de Rhombus usa 10000,10000 (10 segundos en ambas direcciones).

Comportamiento

DirecciónIntervaloQué ocurre en caso de falla
Cliente al servidor10 segundosEl servidor puede cerrar la conexión
Servidor al cliente10 segundosEl cliente debe asumir que la conexión está muerta y reconectar

Implementación

# Sending heartbeats
import threading

def send_heartbeats(ws, stop_event, interval=10):
    while not stop_event.is_set():
        ws.send("\n")
        stop_event.wait(interval)

# Receiving heartbeats
def parse_frame(raw):
    raw = raw.strip("\n\r")
    if not raw or raw == "\x00":
        return None  # This is a heartbeat, safe to ignore
    # ... parse as normal STOMP frame

Guía de análisis de frames

Algoritmo de análisis paso a paso

1. Read WebSocket text message
2. Strip leading newlines/carriage returns
3. If empty or just \x00 → heartbeat, return null
4. Strip trailing \x00
5. Split on "\n\n" (first occurrence) → [header_block, body]
6. Split header_block on "\n" → [command, header1, header2, ...]
7. For each header line, split on first ":" → key, value
8. Return {command, headers, body}

Casos especiales

EntradaResultado
\nHeartbeat (nulo)
\n\n\nHeartbeat (nulo)
\x00Heartbeat (nulo)
Frame sin cuerpoEl cuerpo es una cadena vacía
Valor de header que contiene :Dividir solo en los primeros dos puntos

Intercambio completo de frames

Aquí está la secuencia completa de frames para una sesión típica:
Client                                Server
  │                                      │
  │  CONNECT                             │
  │  accept-version:1.2                  │
  │  heart-beat:10000,10000              │
  │  \x00                               │
  ├─────────────────────────────────────►│
  │                                      │
  │                          CONNECTED   │
  │                          version:1.2 │
  │              heart-beat:10000,10000 │
  │                                \x00  │
  │◄─────────────────────────────────────┤
  │                                      │
  │  SUBSCRIBE                           │
  │  id:sub-0                            │
  │  destination:/topic/change/{org}     │
  │  \x00                               │
  ├─────────────────────────────────────►│
  │                                      │
  │  \n  (heartbeat)                     │
  ├─────────────────────────────────────►│
  │                                      │
  │                     \n  (heartbeat)  │
  │◄─────────────────────────────────────┤
  │                                      │
  │                            MESSAGE   │
  │            destination:/topic/...    │
  │                                      │
  │                  {"entity":"..."}    │
  │                                \x00  │
  │◄─────────────────────────────────────┤
  │                                      │
  │  \n  (heartbeat)                     │
  ├─────────────────────────────────────►│
  │                                      │
  │  DISCONNECT                          │
  │  \x00                               │
  ├─────────────────────────────────────►│
  │                                      │
  │           [WebSocket close]          │
  │◄─────────────────────────────────────┤

Diferencias respecto al STOMP 1.2 completo

La implementación de Rhombus utiliza un subconjunto de STOMP 1.2. Diferencias notables:
CaracterísticaSpec STOMP 1.2Implementación de Rhombus
Comando SENDSoportadoNo se usa (solo push del servidor)
UNSUBSCRIBESoportadoNo es necesario (un solo tópico)
ACK/NACKSoportadoNo se usa (auto-acknowledge)
RECEIPTSoportadoNo se usa
Frame ERRORSoportadoPuede enviarse en errores del servidor
Header content-lengthOpcionalNo requerido
Soporte de transaccionesSoportadoNo se usa
Esto significa que no necesitas una librería completa de cliente STOMP. El subconjunto del protocolo es lo suficientemente simple como para implementarlo manualmente, como se muestra en los Ejemplos de código.
Last modified on April 30, 2026