SVC-turn-o-matic-queue-reservations
Descripción General
API REST de solo lectura consumida exclusivamente por SVC-web-module. Devuelve las reservas activas del día que están disponibles para ser llamadas desde un módulo de atención. SVC-web-module invoca este servicio periódicamente (polling) para obtener la lista actualizada.
Propósito
- Problema que resuelve: SVC-web-module necesita obtener periódicamente las reservas del día que están disponibles para llamar en un módulo de atención específico, filtradas por las líneas asignadas a ese módulo y excluyendo las ya llamadas, canceladas, saltadas o derivadas.
- Usuarios/consumidores principales: SVC-web-module (único consumidor).
- Alternativa si no existiera: SVC-web-module tendría que consultar directamente INFRA-MongoDB y INFRA-Redis para armar la lista de reservas disponibles.
Resumen de Arquitectura
graph LR
WEB[SVC-web-module] -->|GET polling| QR
subgraph QR [SVC-queue-reservations - Express :3000]
API[REST API<br/>solo lectura]
end
subgraph Infraestructura
REDIS[(INFRA-Redis<br/>Cache reservas · Estado · Permisos)]
MONGO[(INFRA-MongoDB<br/>Reservas del día)]
PG[(INFRA-PostgreSQL<br/>Oficinas · Líneas · Permisos)]
end
QR -->|lectura + cache TTL 5s| REDIS
QR -->|fallback si no hay cache| MONGO
QR -->|lectura + cache TTL 180s| PG
- Tipo: service
- Lenguaje/Framework: TypeScript / Express.js 4.19.2
- Runtime: Node.js 20 (Alpine)
- Destino de despliegue: Kubernetes (Helm —
zeroqchartv1.4.1) - Puerto: 3000 (configurable vía
EXPRESS_PORT) - Protocolo: REST (solo lectura — 3 endpoints GET)
- Réplicas en prod: ❓ Pendiente de verificar (definido en chart externo
zeroqchart)
Dependencias
Upstream (servicios que llaman a este)
| Servicio | Método | Endpoint |
|---|---|---|
| SVC-web-module | GET (polling) | /offices/:office_id/modulos/:modulo_id/reservations |
| SVC-web-module | GET (polling) | /offices/:office_id/modulos/:modulo_id/reservations/skipped |
| SVC-web-module | GET (polling) | /offices/:office_id/modulos/:modulo_id/reservations/derivated |
Downstream (servicios que este llama)
| Servicio | Método | Propósito |
|---|---|---|
| Ninguno detectado | — | Este servicio no realiza llamadas HTTP a otros servicios |
Infraestructura
| Componente | Uso | Crítico |
|---|---|---|
| INFRA-MongoDB | Lectura de reservas del día (colección reserves) — fallback cuando no hay datos en Redis | Sí |
| INFRA-PostgreSQL | Lectura de líneas asignadas a módulos y permisos de usuario por oficina | Sí |
| INFRA-Redis | Cache de reservas por oficina (TTL 5s), cache de datos PG (TTL 180s), lectura de estado de reservas canceladas/saltadas/derivadas/llamadas | Sí |
Flujo de Datos
Descripción del flujo principal (GET /offices/:office_id/modulos/:modulo_id/reservations):
- SVC-web-module hace polling con token JWT al endpoint del módulo/oficina
- Se valida el token JWT y se verifican permisos del usuario sobre la oficina consultando INFRA-PostgreSQL (cacheado en INFRA-Redis con TTL 180s)
- Se obtienen las líneas asignadas al módulo desde INFRA-PostgreSQL (cacheado en INFRA-Redis con TTL 180s)
- Se buscan las reservas del día: primero en INFRA-Redis (key
turn-o-matic.state.offices.{id}.reservations.queue, TTL 5s); si no hay cache, se consulta INFRA-MongoDB (colecciónreserves, rango del día en timezone de la oficina) y se cachea el resultado - Por cada reserva de MongoDB, se sincroniza al cache de Redis en keys de estado (
entity,queued,cancelled) - Se filtran las reservas excluyendo las ya llamadas, canceladas, saltadas y derivadas (consultando sets y hashes en INFRA-Redis); se retornan solo las de hoy
- Se ordenan cronológicamente por hora de inicio y se devuelven las primeras 20
Datos sensibles manejados
Este servicio no persiste datos — solo lee y retorna información existente. Los datos PII presentes en las reservas consultadas incluyen:
| Dato | Clasificación | Origen | Retención |
|---|---|---|---|
| email (usuario) | PII | Leído de MongoDB/Redis | No almacena — solo transita |
| phone (usuario) | PII | Leído de MongoDB/Redis | No almacena — solo transita |
| rut (usuario) | PII | Leído de MongoDB/Redis | No almacena — solo transita |
| JWT token | Interno | Header de request | Sesión |
Modos de Falla
| Escenario | Impacto | Mitigación | Severidad |
|---|---|---|---|
| INFRA-MongoDB no disponible | No se pueden consultar reservas (si Redis cache expiró) | Cache en Redis (TTL 5s) mitiga brevemente | Alta |
| INFRA-PostgreSQL no disponible | No se pueden validar oficinas/líneas | Cache en Redis (TTL 180s) | Alta |
| INFRA-Redis no disponible | Sin cache, sin estado de reservas | Retry strategy con backoff exponencial (max 2s, 3 reintentos) | Crítica |
| JWT secret inválido | Todas las peticiones rechazadas | Ninguna detectada | Crítica |
Política de Reintentos / Circuit Breaker
- Intentos de reintento: Redis: 3 reintentos con backoff exponencial (max delay 2000ms), max 10 reconexiones
- Estrategia de backoff: Exponencial para Redis (
retryStrategyen ioredis) - Umbral de circuit breaker: No implementado
- Comportamiento de fallback: No implementado
Monitoreo
Health Check
- Endpoint:
GET /online→{ready: true} - Intervalo: ❓ Pendiente de verificar (configurado en chart externo)
- Timeout: ❓ Pendiente de verificar (configurado en chart externo)
Métricas clave
| Métrica | Umbral de alerta | Dashboard |
|---|---|---|
| Latencia de request p99 | ❓ | ❓ |
| Tasa de errores | ❓ | ❓ |
| Uso de CPU | ❓ | ❓ |
| Uso de memoria | ❓ | ❓ |
Logs
- Formato: JSON estructurado (Winston)
- Nivel por defecto:
info(producción),debug(desarrollo) - Destino: Console (stdout) + archivos (
./logs/app.log,./logs/error.log) - Retención: ❓ Pendiente de verificar
- HTTP request logging: Morgan (formato
combined), excluye/online,/metrics,/version - Debug dinámico:
POST /logger/debug/:activepermite activar/desactivar debug en runtime
Consideraciones de Seguridad
- Autenticación requerida (JWT vía header
Authorization) - Autorización por roles — validación de permisos por oficina (
validaOfficePermissions) - Rate limiting configurado
- Validación de entrada implementada (Celebrate/Joi + middleware anti-inyección SQL/XSS)
- Datos sensibles encriptados en reposo
- Datos sensibles encriptados en tránsito (TLS en ingress)
- Logging de auditoría habilitado (solo HTTP request logs, sin audit trail estructurado)
- No expone datos internos en errores (stack traces solo en entornos no-productivos)
Estrategia de Escalamiento
- Tipo: Horizontal (inferido)
- Auto-scaling: ❓ Pendiente de verificar (no visible en codebase, posiblemente en chart externo)
- Réplicas mínimas: ❓ Pendiente de verificar
- Réplicas máximas: ❓ Pendiente de verificar
- Trigger de escalamiento: ❓ Pendiente de verificar
- Limitaciones conocidas: No se detectaron resource limits/requests en los values de Helm; graceful shutdown no implementado (sin handlers para SIGTERM/SIGINT)
Consideraciones de DRP
- RTO: ❓ (Objetivo de Tiempo de Recuperación)
- RPO: ❓ (Objetivo de Punto de Recuperación)
- Estrategia de respaldo: ❓ Pendiente de verificar
- Failover automático: ❓ Pendiente de verificar
- Runbook: PROC-DRP-turn-o-matic-queue-reservations
Servicios Relacionados
Dataview LIST
LIST
FROM "01-Architecture/Services"
WHERE contains(related_services, this.file.link)
Esta query se ejecuta dinámicamente en Obsidian.
Preguntas Abiertas
- ❓ Owner del servicio: Pendiente de asignar
- ❓ Réplicas en producción: Definido en chart externo
zeroqchart, no visible en el repositorio - ❓ Auto-scaling (HPA): No visible en el repositorio, posiblemente configurado en el chart externo
- ❓ Resource limits/requests: No definidos en los values de Helm del repositorio
- ❓ Retención de logs: No configurada explícitamente
- ❓ docs-config.json desactualizado: El archivo OpenAPI (
src/entrypoints/http/docs-config.json) contiene endpoints de otro servicio (creación de reservas, templates, excepciones, bloques) que no existen en este codebase — debería eliminarse o actualizarse - ❓ Log engañoso en index.ts: Línea 17 registra
connected to RabbitMQpero no existe conexión a RabbitMQ en el servicio - ❓ Métricas y tracing: Endpoint
/metricsreferenciado pero no implementado — sin instrumentación de Prometheus, OpenTelemetry ni APM - ❓ Graceful shutdown: No implementado — sin handlers para SIGTERM/SIGINT, riesgo de pérdida de requests en vuelo durante redeploys
- ❓ Circuit breaker: No implementado para ninguna dependencia
- ❓ Rate limiting: No configurado, la API está expuesta sin throttling
- ❓ RTO/RPO: Sin definir
- ❓ Estrategia de respaldo y failover: Sin definir
- ❓ Compliance: Sin features de GDPR u otra regulación de protección de datos