NotificationOutbox
Overview
Este módulo en services/api/src/models/NotificationOutbox.js define el esquema Mongoose que persiste la cola de notificaciones salientes. El modelo guarda el tipo de evento, el destinatario, el canal de entrega, el estado operativo y los metadatos asociados al envío.
También fija reglas de validación, índices de acceso y retención automática. El archivo exporta NotificationOutbox para uso del backend y NOTIFICATION_EVENT_TYPES para reutilizar el catálogo de eventos permitido.
[!NOTE]
EVENT_TYPEStambién vive ennotifications/notification.events.js. En este archivo actúa como la fuente de verdad del esquema y debe mantenerse sincronizado con ese módulo cuando se implemente.
How it works
flowchart TD
E[EVENT_TYPES] --> S[NotificationOutboxSchema]
S --> V[eventType validation]
S --> U[recipientUserId ref User]
S --> C[recipientChannel validation]
S --> P[payload data]
S --> T[status tracking]
S --> A[attempts and lastError]
S --> D[availableAt and sentAt]
S --> I[index definitions]
S --> O[notification_outbox collection]
N[notification service] --> M[providerMessageId assignment]
M --> O
O --> X[MongoDB TTL cleanup]
NotificationOutboxSchema valida cada documento antes de guardarlo en MongoDB. El modelo registra índices para consultar filas por estado, fecha de disponibilidad y usuario. notification.service.js asigna providerMessageId solo tras un envío exitoso, y MongoDB elimina los documentos al vencer la retención.
Key components
Estos son los elementos principales que expone este archivo y su responsabilidad dentro del flujo de notificaciones.
{
"title": "NotificationOutbox",
"content": "Modelo Mongoose que persiste la cola de notificaciones en la colecci\u00f3n notification_outbox. Valida eventos, destinatarios, estado de entrega y metadatos operativos.",
"type": "class",
"filePath": "services/api/src/models/NotificationOutbox.js",
"badges": [
"public"
]
}
{
"title": "NOTIFICATION_EVENT_TYPES",
"content": "Exportaci\u00f3n p\u00fablica del cat\u00e1logo de eventType admitido por el esquema. Reexpone EVENT_TYPES para reutilizaci\u00f3n en otros m\u00f3dulos.",
"type": "enum",
"filePath": "services/api/src/models/NotificationOutbox.js",
"badges": [
"public"
]
}
Data & fields
El esquema combina campos obligatorios, campos opcionales y campos automáticos generados por Mongoose. La colección fija es notification_outbox, y el modelo usa timestamps: true.
[
{
"name": "eventType",
"type": "string",
"required": true,
"description": "Tipo de evento validado contra EVENT_TYPES."
},
{
"name": "recipientUserId",
"type": "ObjectId | null",
"description": "Referencia opcional al modelo User. Su valor por defecto es null."
},
{
"name": "recipientChannel",
"type": "string",
"required": true,
"description": "Canal de entrega. Solo admite primary_email o retention_contact."
},
{
"name": "payload",
"type": "Schema.Types.Mixed",
"description": "Carga útil flexible del evento. Su valor por defecto es un objeto vacío."
},
{
"name": "status",
"type": "string",
"description": "Estado de la fila. Sus valores permitidos son pending, sending, sent, failed y dead_letter."
},
{
"name": "attempts",
"type": "number",
"description": "Contador de intentos de envío. Su valor por defecto es 0."
},
{
"name": "lastError",
"type": "string",
"description": "Último error registrado durante el envío. Su valor por defecto es una cadena vacía."
},
{
"name": "availableAt",
"type": "date",
"description": "Fecha desde la cual el registro queda disponible. Su valor por defecto es Date.now."
},
{
"name": "sentAt",
"type": "date",
"description": "Fecha del envío exitoso. Su valor por defecto es null."
},
{
"name": "providerMessageId",
"type": "string | null",
"description": "Identificador devuelto por el proveedor tras un envío exitoso. Solo se asigna desde notification.service.js."
},
{
"name": "createdAt",
"type": "date",
"description": "Campo automático generado por timestamps. Participa en el índice TTL."
},
{
"name": "updatedAt",
"type": "date",
"description": "Campo automático generado por timestamps."
}
]
eventType
Este campo es obligatorio y controla qué tipo de notificación representa el documento. El esquema valida su valor contra EVENT_TYPES.
ACCOUNT_DELETION_REQUESTEDACCOUNT_RESTORATION_LINK_RESENTACCOUNT_RESTOREDACCOUNT_ANONYMIZEDACCOUNT_PURGE_WARNINGACCOUNT_PURGEDPASSWORD_RESET_REQUESTEDPASSWORD_CREATEDEMAIL_VERIFICATION_REQUESTEDWELCOMELISTING_INTEREST_RECEIVEDLISTING_COMMENT_RECEIVEDLEAD_CREATED_DURING_PROTECTIONLEAD_CREATED_DURING_ANONYMIZATIONLISTING_PERFORMANCE_DIGEST
recipientChannel
Este campo indica cómo se resuelve el destino del mensaje en el momento del envío. El comentario del código aclara que puede apuntar al email principal del usuario o al retentionContact cifrado.
primary_emailretention_contact
status
Este campo controla el ciclo de vida operativo de la fila. El valor por defecto es pending, y el esquema lo indexa junto con availableAt.
pendingsendingsentfaileddead_letter
timestamps y retención
Mongoose agrega createdAt y updatedAt mediante timestamps: true. El índice TTL usa createdAt como base temporal para la expiración automática. El documento no guarda la dirección cruda del destinatario en este modelo.
Behaviors
El archivo define comportamientos de validación, indexación y persistencia que sostienen el envío de notificaciones.
NotificationOutboxSchema.index({ status: 1, availableAt: 1 })— crea un índice compuesto para consultas por estado y fecha de disponibilidad.NotificationOutboxSchema.index({ recipientUserId: 1, createdAt: -1 })— acelera las consultas por usuario, ordenadas de más recientes a más antiguas.NotificationOutboxSchema.index({ createdAt: 1 }, { expireAfterSeconds: RETENTION_TTL_SECONDS })— activa la eliminación automática tras 90 días.mongoose.model('NotificationOutbox', NotificationOutboxSchema)— registra el modelo Mongoose para que otros módulos lo consuman.NOTIFICATION_EVENT_TYPES— expone el mismo catálogo queEVENT_TYPESpara compartirlo con otras partes del backend.
Gotchas & edge cases
[!WARNING]
providerMessageIdno se acepta desde una entrada externa. El comentario del archivo indica que solo se asigna desdenotification.service.jsdespués de un envío exitoso.
[!CAUTION] La retención TTL usa una única regla de 90 días basada en
createdAt. No distingue porstatus.
[!NOTE] El propio esquema trata
pendingysendingcomo estados transitorios.failedno depende de un proceso automático de diagnóstico posterior.
[!IMPORTANT] El esquema no guarda la dirección de correo en texto plano. Solo persiste el
recipientChannel, y la resolución del destino ocurre en el momento del envío.
Related
Este modelo se conecta con otros componentes del backend que participan en la entrega y la auditoría de notificaciones.
notifications/notification.events.js— catálogo hermano de eventos que debe permanecer sincronizado conEVENT_TYPES.notification.service.js— servicio que asignaproviderMessageIddespués de un envío exitoso.User— modelo referenciado porrecipientUserId.- MongoDB TTL monitor — proceso nativo que elimina los documentos cuando vence la retención.
- Colección
notification_outbox— almacenamiento persistente de las filas de notificación.