Las mutaciones del dominio y las filas del outbox comparten una transacción de base de datos; un relay publica al menos una vez; los consumidores son idempotentes; está prohibido escribir en la base de datos y en un broker de forma independiente sin un outbox.
Estado del paquete: contexto de referencia listo para revisión humana. El contrato y los escenarios de prueba están completos, pero no se afirma que una implementación adoptante los haya superado.
Decisión
Cuando una mutación del dominio debe notificar a otros servicios, la fila del evento se inserta en la misma transacción que la mutación. Un relay publicador lee filas no publicadas del outbox y las entrega al broker al menos una vez. Los consumidores tratan los duplicados como ya procesados usando un evento o clave de deduplicación. El código de la aplicación no debe escribir en la base de datos y luego producir de forma independiente a un broker sin este outbox (o un inbox transaccional equivalente en el otro lado).
Alcance
- Tabla de outbox transaccional, polling del relay o seguimiento de log, publicación al menos una vez, idempotencia del consumidor y envenenamiento de cargas útiles no entregables.
- Agregados backend que emiten eventos de dominio.
- Coordinación con la visibilidad de la cola de trabajos para los workers del relay.
Fuera de este bloque
- Reglas de evolución del esquema de la carga útil del evento.
- Firma de webhooks hacia terceros después de que el evento ya está en el broker.
Contrato
- El commit del cambio del agregado es atómico con la inserción de uno o más registros en el outbox para ese cambio.
- Los registros del outbox incluyen
event_id,aggregate_id,occurred_at,payloadypublish_statecon estados pendiente, publicado o fallido. - El relay marca como publicado solo después de que el broker lo reconoce; los fallos antes del ack reintentan el mismo
event_id. - Los consumidores ignoran duplicados de
event_id(o clave de idempotencia equivalente) después de la primera aplicación exitosa. - La escritura dual sin una fila de outbox en la transacción de mutación es una violación de política detectada en revisión y en una verificación estática opcional.
- Los mensajes envenenados que fallan al decodificar después de un presupuesto se mueven a
failedcon una ruta para operador; no bloquean el relay completo indefinidamente.
Implementación
- Insertar la fila del outbox en la misma conexión que la mutación del agregado.
- El relay opera en pequeños lotes con reclamo skip-locked; poner identidad de esquema en la carga útil.
Manejo de fallos
- Si el broker está caído, las filas pendientes se acumulan y las mutaciones aún se confirman.
- Solo los ids reconocidos se marcan como publicados; las cargas útiles sobredimensionadas fallan solo esa fila.
Verificación
- Fallo después del commit y antes del ack; el reinicio debe republicar los ids pendientes.
- Un consumidor que ve el mismo event_id dos veces aplica solo una vez; la escritura dual sin fila de outbox es un defecto.
Los ejemplos con apariencia ejecutable en este paquete son fixtures y contratos de aceptación. Ejecute
python tools/validate.py desde la raíz de la colección para verificar la estructura y metadatos del paquete; luego
implemente y ejecute los escenarios en el repositorio objetivo.
Suposiciones para adopción
- Los nombres y valores numéricos en
example.yamlson un perfil de adopción, no valores predeterminados universales. - El equipo adoptante debe mapear actores, clases de datos, vocabulario de errores y propiedad a su sistema.
Referencias
- El patrón de outbox transaccional se describe en https://microservices.io/patterns/data/transactional-outbox.html.
- Los sobres de eventos pueden seguir CloudEvents cuando el equipo adoptante elige ese sobre; la publicación al menos una vez más la idempotencia del consumidor siguen siendo requeridas independientemente del sobre.