michangarrito/docs/97-adr/ADR-0004-notifications-realtime.md
rckrdmrd 2c916e75e5 [SIMCO-V4] feat: Agregar documentación SaaS, ADRs e integraciones
Nuevas Épicas (MCH-029 a MCH-033):
- Infraestructura SaaS multi-tenant
- Auth Social (OAuth2)
- Auditoría Empresarial
- Feature Flags
- Onboarding Wizard

Nuevas Integraciones (INT-010 a INT-014):
- Email Providers (SendGrid, Mailgun, SES)
- Storage Cloud (S3, GCS, Azure)
- OAuth Social
- Redis Cache
- Webhooks Outbound

Nuevos ADRs (0004 a 0011):
- Notifications Realtime
- Feature Flags Strategy
- Storage Abstraction
- Webhook Retry Strategy
- Audit Log Retention
- Rate Limiting
- OAuth Social Implementation
- Email Multi-provider

Actualizados:
- MASTER_INVENTORY.yml
- CONTEXT-MAP.yml
- HERENCIA-SIMCO.md
- Mapas de documentación

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:43:15 -06:00

182 lines
4.0 KiB
Markdown

---
id: ADR-0004
type: ADR
title: "Notificaciones en Tiempo Real"
status: Accepted
decision_date: 2026-01-10
updated_at: 2026-01-10
simco_version: "4.0.1"
stakeholders:
- "Equipo MiChangarrito"
tags:
- notifications
- websocket
- sse
- realtime
---
# ADR-0004: Notificaciones en Tiempo Real
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | ADR-0004 |
| **Estado** | Accepted |
| **Fecha** | 2026-01-10 |
| **Autor** | Architecture Team |
| **Supersede** | - |
---
## Contexto
MiChangarrito necesita notificar a los usuarios en tiempo real sobre eventos como nuevos pedidos, pagos recibidos, alertas de inventario y actualizaciones de estado. Se requiere una solucion que funcione tanto en web como en mobile.
---
## Decision
**Adoptamos Server-Sent Events (SSE) para notificaciones web y push notifications nativas para mobile.**
SSE es unidireccional (servidor -> cliente), suficiente para notificaciones, mas simple de implementar que WebSockets, y funciona mejor con proxies y load balancers.
```typescript
// Endpoint SSE
@Get('notifications/stream')
@Sse()
notificationStream(@Req() req: Request): Observable<MessageEvent> {
const userId = req.user.id;
return this.notificationService.getUserStream(userId);
}
```
---
## Alternativas Consideradas
### Opcion 1: WebSockets (Socket.io)
- **Pros:**
- Bidireccional
- Ampliamente soportado
- Buena libreria (Socket.io)
- **Cons:**
- Mas complejo de escalar
- Requiere sticky sessions
- Overhead para notificaciones unidireccionales
### Opcion 2: Server-Sent Events (Elegida)
- **Pros:**
- Simple de implementar
- Unidireccional (perfecto para notificaciones)
- Reconexion automatica
- Funciona sobre HTTP/2
- No requiere sticky sessions
- **Cons:**
- Solo unidireccional
- Limite de conexiones por dominio
- No soportado en IE
### Opcion 3: Polling
- **Pros:**
- Muy simple
- Funciona en cualquier navegador
- **Cons:**
- Ineficiente
- Latencia alta
- Carga innecesaria al servidor
---
## Consecuencias
### Positivas
1. **Simplicidad:** SSE es nativo del navegador
2. **Escalabilidad:** Funciona con load balancers
3. **Eficiencia:** Conexion persistente sin overhead
4. **Resiliencia:** Reconexion automatica
### Negativas
1. **Limite conexiones:** 6 por dominio en HTTP/1.1
2. **Solo unidireccional:** Si necesitamos bidireccional, agregar WebSocket
3. **IE no soportado:** Usar polyfill si es necesario
---
## Implementacion
### Backend (NestJS)
```typescript
@Controller('notifications')
export class NotificationController {
constructor(
private readonly notificationService: NotificationService,
) {}
@Get('stream')
@UseGuards(JwtAuthGuard)
@Sse()
stream(@Req() req: Request): Observable<MessageEvent> {
const userId = req.user.id;
const tenantId = req.user.tenantId;
return this.notificationService
.createStream(userId, tenantId)
.pipe(
map(notification => ({
data: notification,
type: notification.type,
id: notification.id,
})),
);
}
}
```
### Frontend (React)
```typescript
function useNotifications() {
const [notifications, setNotifications] = useState([]);
useEffect(() => {
const eventSource = new EventSource('/api/notifications/stream', {
withCredentials: true,
});
eventSource.onmessage = (event) => {
const notification = JSON.parse(event.data);
setNotifications(prev => [notification, ...prev]);
toast.info(notification.message);
};
eventSource.onerror = () => {
// Reconexion automatica
};
return () => eventSource.close();
}, []);
return notifications;
}
```
### Mobile (Push Notifications)
Para mobile, usamos push notifications nativas en lugar de SSE para mejor experiencia cuando la app esta en background.
---
## Referencias
- [MDN Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)
- [NestJS SSE](https://docs.nestjs.com/techniques/server-sent-events)
---
**Fecha decision:** 2026-01-10
**Autores:** Architecture Team