- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.8 KiB
5.8 KiB
| id | title | type | status | priority | supersedes | superseded_by | version | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|---|
| ADR-004 | Sistema de Notificaciones Real-time | ADR | Accepted | P0 | N/A | N/A | 1.0.0 | 2026-01-07 | 2026-01-10 |
ADR-004: Sistema de Notificaciones Real-time
Metadata
| Campo | Valor |
|---|---|
| ID | ADR-004 |
| Estado | Accepted |
| Fecha | 2026-01-10 |
| Supersede | N/A |
Contexto
Template SaaS necesita un sistema de notificaciones que soporte:
- Múltiples canales (email, push, in-app, SMS)
- Entrega en tiempo real
- Preferencias de usuario
- Templates reutilizables
- Cola para procesamiento asíncrono
- Tracking de entrega
Opciones Consideradas
Opción 1: Polling
Descripción: Cliente hace requests periódicos para verificar nuevas notificaciones.
Pros:
- Simple de implementar
- Sin infraestructura adicional
Contras:
- Latencia alta
- Desperdicio de recursos
- Mala experiencia de usuario
Opción 2: Server-Sent Events (SSE)
Descripción: Conexión unidireccional server→client.
Pros:
- Simple
- Reconexión automática
- Soportado nativamente
Contras:
- Solo unidireccional
- Límite de conexiones por dominio
- No ideal para bidireccional
Opción 3: WebSocket + BullMQ ✓
Descripción: WebSocket para real-time + cola para procesamiento.
Pros:
- Bidireccional
- Baja latencia
- Cola confiable
- Escalable horizontalmente
- Retry automático
Contras:
- Más complejo
- Requiere Redis
- Manejo de reconexiones
Decisión
Elegimos WebSocket (Socket.io) + BullMQ porque:
- Real-time: WebSocket para entrega instantánea
- Confiabilidad: BullMQ para procesamiento garantizado
- Escalabilidad: Redis permite múltiples instancias
- Multi-canal: Cola maneja diferentes canales
Implementación
Arquitectura
┌─────────────┐ ┌─────────────┐
│ Client │◀───▶│ WebSocket │
│ (React) │ │ Gateway │
└─────────────┘ └─────────────┘
│
┌──────▼──────┐
│ Redis │
│ (Pub/Sub) │
└──────┬──────┘
│
┌─────────────┐ ┌──────▼──────┐
│ BullMQ │◀───▶│ Workers │
│ Queues │ │ │
└─────────────┘ └─────────────┘
│ │
│ ┌──────▼──────┐
│ │ Email │
│ │ Push │
│ │ SMS │
└───────────▶└─────────────┘
Canales Soportados
| Canal | Provider | Uso |
|---|---|---|
| SendGrid/SES | Transaccional, marketing | |
| Push | Web Push API | Alertas importantes |
| In-app | WebSocket | Notificaciones UI |
| SMS | Twilio | (Futuro) |
| Meta API | (Sprint 5) |
WebSocket Gateway
@WebSocketGateway({
namespace: '/notifications',
cors: { origin: '*' },
})
export class NotificationsGateway {
@SubscribeMessage('subscribe')
handleSubscribe(client: Socket, payload: { tenantId: string }) {
client.join(`tenant:${payload.tenantId}`);
}
async sendToUser(userId: string, notification: Notification) {
this.server.to(`user:${userId}`).emit('notification', notification);
}
async sendToTenant(tenantId: string, notification: Notification) {
this.server.to(`tenant:${tenantId}`).emit('notification', notification);
}
}
Queue Processing
@Processor('notifications')
export class NotificationProcessor {
@Process('send')
async handleSend(job: Job<NotificationJob>) {
const { notification, channels } = job.data;
for (const channel of channels) {
switch (channel) {
case 'email':
await this.emailService.send(notification);
break;
case 'push':
await this.pushService.send(notification);
break;
case 'in_app':
await this.gateway.sendToUser(notification.userId, notification);
break;
}
}
}
}
Push Notifications (VAPID)
// Generar VAPID keys
const vapidKeys = webPush.generateVAPIDKeys();
// Enviar push
await webPush.sendNotification(subscription, JSON.stringify({
title: notification.title,
body: notification.body,
icon: '/icon.png',
data: { url: notification.actionUrl },
}));
Preferencias de Usuario
interface NotificationPreferences {
email: {
marketing: boolean;
transactional: boolean;
digest: 'none' | 'daily' | 'weekly';
};
push: {
enabled: boolean;
alerts: boolean;
updates: boolean;
};
inApp: {
enabled: boolean;
sound: boolean;
};
}
Consecuencias
Positivas
- Entrega instantánea con WebSocket
- Confiabilidad con colas
- Multi-canal flexible
- Escalable horizontalmente
- User preferences respetadas
Negativas
- Complejidad adicional
- Dependencia de Redis
- Costos de proveedores externos
- Manejo de estados de conexión
Monitoreo
- Queue metrics (jobs pending, failed)
- WebSocket connections activas
- Delivery rates por canal
- Error rates
Referencias
- Socket.io Documentation
- BullMQ Documentation
- Web Push Protocol
- Implementación:
apps/backend/src/modules/notifications/
Fecha decision: 2026-01-10 Autores: Claude Code (Arquitectura)