Repositorio de NotificationOutbox

Overview

El archivo services/api/src/modules/notifications/notification.repository.js centraliza la persistencia del outbox de notificaciones. Expone helpers asíncronos para crear registros y cambiar su estado dentro de NotificationOutbox .

Este módulo no envía correos ni coordina proveedores. La propia fuente aclara que la entrega vive en notification.service.js, y que este repositorio no conoce proveedores, reintentos ni workers .

[!NOTE] El repositorio es una capa de escritura pura. Solo opera sobre NotificationOutbox y devuelve el resultado crudo de create o updateOne .

How it works

El flujo es corto y determinista:

  • createOutboxEntry(...) inserta un documento nuevo en NotificationOutbox con los datos del evento.
  • markOutboxEntrySending(outboxEntryId) marca el documento como sending y suma un intento.
  • markOutboxEntrySent(outboxEntryId, providerMessageId) lo marca como sent y guarda la marca temporal del envío.
  • markOutboxEntryFailed(outboxEntryId, errorCode) lo marca como failed y guarda el código de error.

Estas funciones trabajan por _id, sin cargar el documento antes de actualizarlo. Tampoco interpretan la respuesta de updateOne; solo la reenvían al llamador .

Key components

{
    "title": "createOutboxEntry",
    "content": "Persiste un nuevo documento en NotificationOutbox con eventType, recipientUserId, recipientChannel y payload.",
    "type": "function",
    "filePath": "services/api/src/modules/notifications/notification.repository.js",
    "badges": [
        "public"
    ]
}
{
    "title": "markOutboxEntrySending",
    "content": "Actualiza un outbox entry por _id, lo pasa a sending, limpia lastError y aumenta attempts.",
    "type": "function",
    "filePath": "services/api/src/modules/notifications/notification.repository.js",
    "badges": [
        "public"
    ]
}
{
    "title": "markOutboxEntrySent",
    "content": "Actualiza un outbox entry por _id, lo pasa a sent, guarda sentAt, limpia lastError y opcionalmente persiste providerMessageId.",
    "type": "function",
    "filePath": "services/api/src/modules/notifications/notification.repository.js",
    "badges": [
        "public"
    ]
}
{
    "title": "markOutboxEntryFailed",
    "content": "Actualiza un outbox entry por _id, lo pasa a failed y almacena el errorCode en lastError.",
    "type": "function",
    "filePath": "services/api/src/modules/notifications/notification.repository.js",
    "badges": [
        "public"
    ]
}

Data & fields

El archivo no define el esquema, pero sí usa estos campos en NotificationOutbox. El comportamiento observado en la fuente depende de ellos.

[
    {
        "name": "eventType",
        "type": "string",
        "required": true,
        "description": "Tipo de evento que se persiste en el outbox."
    },
    {
        "name": "recipientUserId",
        "type": "string | null",
        "description": "Identificador del usuario destinatario. En createOutboxEntry tiene valor por defecto null."
    },
    {
        "name": "recipientChannel",
        "type": "string",
        "required": true,
        "description": "Canal de destino guardado en el registro del outbox."
    },
    {
        "name": "payload",
        "type": "object",
        "description": "Carga útil asociada al evento. En createOutboxEntry tiene valor por defecto {}."
    }
]
[
    {
        "name": "status",
        "type": "string",
        "required": true,
        "description": "Se fija en sending, sent o failed según la operación."
    },
    {
        "name": "attempts",
        "type": "number",
        "description": "Se incrementa en markOutboxEntrySending."
    },
    {
        "name": "lastError",
        "type": "string",
        "description": "Se limpia al marcar sending o sent, y se llena con errorCode al fallar."
    },
    {
        "name": "sentAt",
        "type": "Date",
        "description": "Se establece en markOutboxEntrySent con la fecha actual."
    },
    {
        "name": "providerMessageId",
        "type": "string | null",
        "description": "Se guarda solo en markOutboxEntrySent. La fuente indica que es un dato interno."
    }
]

[!IMPORTANT] La fuente comenta que providerMessageId es opcional y debe venir solo del caller interno. No debe originarse en input externo .

Behaviors

  • createOutboxEntry [badge:public] crea un documento nuevo en NotificationOutbox y devuelve el resultado de NotificationOutbox.create(...) .
  • markOutboxEntrySending [badge:public] actualiza un documento por _id, fija status: 'sending', limpia lastError y suma attempts con $inc .
  • markOutboxEntrySent [badge:public] actualiza un documento por _id, fija status: 'sent', escribe sentAt, limpia lastError y guarda providerMessageId si existe .
  • markOutboxEntryFailed [badge:public] actualiza un documento por _id, fija status: 'failed' y escribe lastError con el código recibido .

Workflows

  • notification.events.js usa createOutboxEntry para registrar eventos de dominio en el outbox antes de intentar su entrega síncrona .
  • notification.service.js usa markOutboxEntrySending, markOutboxEntrySent y markOutboxEntryFailed durante deliverOutboxEntry .
  • notification.service.js también resuelve el destinatario y envía el mensaje, mientras este repositorio solo persiste estado .

Gotchas & edge cases

[!WARNING] Este módulo no valida la existencia del documento ni transforma el resultado de updateOne. Si _id no coincide, la llamada sigue devolviendo el resultado crudo de la operación de base de datos .

[!WARNING] El repositorio no maneja entrega, reintentos ni workers. Esa responsabilidad pertenece a notification.service.js, según el comentario de la fuente .

[!NOTE] El modelo relacionado NotificationOutbox tiene un TTL de 90 días sobre createdAt, y providerMessageId existe con default null, según sus pruebas de esquema .

  • services/api/src/modules/notifications/notification.service.js coordina la entrega real y usa este repositorio para cambiar estados del outbox .
  • services/api/src/modules/notifications/notification.events.js registra eventos de dominio y crea entradas de outbox antes de la entrega .
  • services/api/src/models/NotificationOutbox.js es el modelo persistente sobre el que opera este archivo; sus pruebas confirman el TTL y el campo providerMessageId .