Notifications Service
1. Descripción
Microservicio encargado de orquestar comunicaciones multicanal (correo, SMS, webhooks internos) en respuesta a eventos del dominio. Implementa el agregado NotificacionPendiente y coordina plantillas dinámicas por tipo de evento.
Bounded Context: Comunicaciones y Alertas
Repository: eventmesh-lab/notifications-service
2. Responsabilidades
- Recibir eventos de dominio y mapearlos a plantillas de notificación
- Gestionar preferencias de usuario (canales habilitados, idioma)
- Programar, reintentar y auditar entregas
- Emitir eventos de confirmación o fallo a servicios consumidores
- Exponer APIs para notificaciones ad-hoc o campañas masivas
3. Modelo de Dominio
3.1 Agregado: NotificacionPendiente
Root Aggregate: NotificacionPendiente
Entidades
NotificacionPendiente
public class NotificacionPendiente : AggregateRoot
{
public Guid Id { get; private set; }
public Guid DestinatarioId { get; private set; }
public CanalPreferido Canal { get; private set; }
public string PlantillaId { get; private set; }
public IDictionary<string, string> Datos { get; private set; }
public EstadoNotificacion Estado { get; private set; }
public int Intentos { get; private set; }
public DateTime FechaCreacion { get; private set; }
public DateTime? UltimoIntento { get; private set; }
}
PreferenciasUsuario
public class PreferenciasUsuario : Entity
{
public Guid UsuarioId { get; private set; }
public bool EmailHabilitado { get; private set; }
public bool SmsHabilitado { get; private set; }
public bool PushHabilitado { get; private set; }
public string Idioma { get; private set; }
}
Value Objects
EstadoNotificacion
public enum EstadoNotificacion
{
Pendiente,
EnProceso,
Entregada,
Fallida,
Cancelada
}
Canal
public enum Canal
{
Email,
Sms,
Push,
Webhook
}
4. Comandos del Dominio
CrearNotificacion
Descripción: Registra una notificación a partir de un evento recibido.
Input:
public record CrearNotificacionCommand
{
public Guid DestinatarioId { get; init; }
public string Evento { get; init; }
public IDictionary<string, string> Datos { get; init; }
}
Validaciones: - Debe existir plantilla configurada para el evento - El destinatario debe tener al menos un canal habilitado
Emite: NotificacionCreada
MarcarNotificacionEntregada
Descripción: Confirma la entrega satisfactoria.
Input:
public record MarcarNotificacionEntregadaCommand
{
public Guid NotificacionId { get; init; }
public string ProveedorMensajeId { get; init; }
}
Emite: NotificacionEntregada
ReintentarNotificacion
Descripción: Reprograma una notificación fallida.
Input:
public record ReintentarNotificacionCommand
{
public Guid NotificacionId { get; init; }
}
Validaciones: - Máximo 5 intentos - Si falló por preferencia inválida, no reintentar
Emite: NotificacionReintentada
5. Eventos de Dominio
NotificacionCreada
public record NotificacionCreada : DomainEvent
{
public Guid NotificacionId { get; init; }
public Guid DestinatarioId { get; init; }
public Canal Canal { get; init; }
}
Suscriptores:
- deliveries-worker: Envía mensaje al proveedor externo
NotificacionEntregada
public record NotificacionEntregada : DomainEvent
{
public Guid NotificacionId { get; init; }
public Guid DestinatarioId { get; init; }
public DateTime FechaEntrega { get; init; }
public string Canal { get; init; }
}
Suscriptores:
- analytics-service: Actualiza métricas de engagement
- events-service: Puede avanzar flujo de publicación
NotificacionFallida
public record NotificacionFallida : DomainEvent
{
public Guid NotificacionId { get; init; }
public string Motivo { get; init; }
public int Intentos { get; init; }
}
Suscriptores:
- support-service: Abre ticket si supera umbral
6. Reglas de Negocio
- Idempotencia por evento: Se evita duplicidad usando
Evento+Destinatariocomo llave de negocio. - Prioridad de canales: Orden configurable (ej. email → push → SMS).
- Horarios silenciosos: No enviar SMS entre 23:00 y 07:00 en huso del usuario.
- Plantillas versionadas: Cambios se auditan y requieren aprobación.
- Retención: Datos personales se eliminan tras 30 días.
7. Integraciones
Comunicación Asíncrona (RabbitMQ)
Exchange: notifications.domain.events
Publica:
- NotificacionEntregada
- NotificacionFallida
Consume:
- PagoConfirmado (desde payments-service)
- HiloPublicado (desde forums-service)
- TransmisionIniciada (desde streaming-service)
- TicketConfirmado (desde tickets-service)
8. Persistencia
Base de Datos: PostgreSQL
Tabla: notificaciones
CREATE TABLE notificaciones (
id UUID PRIMARY KEY,
destinatario_id UUID NOT NULL,
canal VARCHAR(20) NOT NULL,
plantilla_id VARCHAR(100) NOT NULL,
estado VARCHAR(20) NOT NULL,
intentos INT NOT NULL,
datos JSONB NOT NULL,
fecha_creacion TIMESTAMP NOT NULL,
ultimo_intento TIMESTAMP
);
Tabla: preferencias_usuario
CREATE TABLE preferencias_usuario (
usuario_id UUID PRIMARY KEY,
email_habilitado BOOLEAN NOT NULL,
sms_habilitado BOOLEAN NOT NULL,
push_habilitado BOOLEAN NOT NULL,
idioma VARCHAR(10) NOT NULL,
canales_bloqueados JSONB
);
9. API Endpoints
POST /api/notificaciones
Crea una notificación manual.
Request:
{
"destinatarioId": "uuid",
"evento": "PagoConfirmado",
"datos": {
"monto": "50.00",
"moneda": "USD"
}
}
GET /api/notificaciones/{id}
Obtiene detalle y tracking de una notificación.
PUT /api/preferencias/{usuarioId}
Actualiza preferencias y canales habilitados.
10. Observabilidad
- Métricas Prometheus:
notificaciones_en_cola_total,notificaciones_fallidas_total - Tracing: Propaga contexto W3C desde origen del evento
- Alertas: Umbral de fallos consecutivos > 5 genera alerta crítica