Appearance
Cache y Optimizaciones del Modulo de Membresias
Modulo: Membresias Tipo: Resource Estado: Implementado Fecha: 2026-01-27
Descripcion
Problema que resuelve
El modulo de membresias consulta frecuentemente datos maestros que cambian con poca frecuencia, como las categorias de membresia y las disciplinas. Cada vez que se carga un listado de miembros, se consultan estas entidades para enriquecer la informacion. Sin un mecanismo de cache, esto genera:
- Consultas repetitivas: Las categorias y disciplinas se consultan una y otra vez desde la base de datos aunque no hayan cambiado
- Carga innecesaria en la base de datos: En operaciones masivas como la facturacion por lotes que procesan cientos de miembros, las mismas categorias se consultan repetidamente
- Tiempos de respuesta lentos: Los listados de miembros con datos enriquecidos tardan mas de lo necesario por las consultas redundantes
- Problemas en entorno multi-tenant: Sin aislamiento de cache por tenant, los datos de una sucursal podrian mezclarse con los de otra
Ademas, las consultas de datos relacionados de miembros (categorias, disciplinas, productos) generan el problema de N+1 queries cuando se cargan individualmente para cada miembro de un listado.
Solucion implementada
Se implementan dos mecanismos de optimizacion complementarios:
- Cache multi-tenant para datos maestros: Sistema de cache con aislamiento por tenant (sucursal/caja) para categorias y disciplinas del modulo de membresias, con tiempo de vida configurable e invalidacion automatica
- Carga por lotes (batch loading): Consultas agrupadas para obtener datos relacionados de multiples miembros en una sola operacion
Valor de negocio
- Respuesta mas rapida: Los datos maestros se sirven desde cache en lugar de consultar la base de datos en cada solicitud
- Menor carga en la base de datos: Se reducen significativamente las consultas a categorias y disciplinas
- Aislamiento garantizado: Cada sucursal/caja tiene su propio cache, sin riesgo de mezcla de datos entre tenants
- Consistencia asegurada: La invalidacion automatica garantiza que los datos en cache se actualicen cuando hay cambios
- Escalabilidad: El sistema mantiene buen rendimiento al crecer la cantidad de usuarios concurrentes y tenants
Contexto del sistema
Estos mecanismos se integran con:
- Servicio de categorias de membresia: Consulta y gestion de categorias con cache automatico
- Servicio de disciplinas: Consulta de disciplinas con cache automatico
- Servicio de enriquecimiento: Carga por lotes de datos relacionados al enriquecer listados de miembros
- Facturacion por lotes: Consumidor principal que se beneficia de ambas optimizaciones
- Infraestructura multi-tenant: El cache respeta el aislamiento por schema
Proceso de Negocio
Componente 1: Cache Multi-Tenant de Categorias
Flujo de cache de categorias
- Se solicita el listado de categorias de membresia
- El sistema verifica si existen datos en cache para el tenant actual
- Si hay cache vigente: Se devuelven los datos desde cache (sin consultar la base de datos)
- Si no hay cache o esta expirado: Se consulta la base de datos, se almacenan los resultados en cache y se devuelven
- Cuando se crea, modifica o elimina una categoria, el cache se invalida automaticamente para el tenant actual
Condiciones para uso de cache
| Condicion | Se usa cache | Motivo |
|---|---|---|
| Consulta simple sin opciones | Si | Consulta mas frecuente, datos estables |
| Consulta con opciones especiales (filtros, includes) | No | Los resultados varian segun las opciones |
| Consulta con alcance diferente a minimo | No | Se necesita la informacion completa actualizada |
Invalidacion del cache
El cache de categorias se invalida automaticamente en las siguientes operaciones:
| Operacion | Invalidacion |
|---|---|
| Crear nueva categoria | Se invalida cache del tenant actual |
| Modificar categoria (completa) | Se invalida cache del tenant actual |
| Modificar categoria (parcial) | Se invalida cache del tenant actual |
| Eliminar categoria | Se invalida cache del tenant actual |
Componente 2: Cache Multi-Tenant de Disciplinas
El mecanismo de cache para disciplinas funciona de manera identica al de categorias:
- Cache con aislamiento por tenant
- Invalidacion automatica al crear, modificar o eliminar disciplinas
- Solo se usa para consultas simples sin opciones especiales
Componente 3: Aislamiento Multi-Tenant del Cache
Mecanismo de aislamiento
El cache almacena datos de forma separada para cada tenant (sucursal/caja):
| Aspecto | Comportamiento |
|---|---|
| Identificacion del tenant | Se obtiene del contexto de la solicitud (sesion del usuario) |
| Separacion de datos | Cada tenant tiene su propio espacio de cache aislado |
| Prefijo del modulo | Los datos de membresia se almacenan bajo el prefijo del modulo para evitar colisiones con otros modulos |
| Tiempo de vida (TTL) | Configurable; los datos expiran automaticamente tras el periodo definido |
Garantia de aislamiento
- Los datos cacheados de una sucursal nunca son visibles ni accesibles por otra sucursal
- La invalidacion de cache de un tenant no afecta al cache de otros tenants
- Cada operacion de invalidacion es especifica al tipo de dato (categorias o disciplinas) y al tenant
Componente 4: Carga por Lotes (Batch Loading)
Problema que resuelve
Al cargar un listado de 50 miembros con sus categorias, disciplinas y productos, sin optimizacion se generarian:
- 50 consultas para categorias (una por miembro)
- 50 consultas para disciplinas (una por miembro)
- 50 consultas para productos (una por miembro)
- Total: 150 consultas adicionales (problema N+1)
Solucion implementada
El sistema agrupa las consultas de datos relacionados:
- Consulta agrupada de relaciones: Una sola consulta obtiene todas las relaciones categoria-miembro, disciplina-miembro o producto-miembro para todos los miembros del listado
- Recoleccion de identificadores unicos: Se identifican las categorias, disciplinas o productos unicos referenciados
- Consulta agrupada de entidades: Una sola consulta obtiene todas las entidades referenciadas
- Mapeo eficiente: Los resultados se mapean a cada miembro correspondiente
Resultado de la optimizacion
| Escenario | Sin optimizacion | Con batch loading |
|---|---|---|
| 50 miembros con categorias | 50 consultas | 2 consultas (relaciones + categorias) |
| 50 miembros con disciplinas | 50+ consultas | 2 consultas (relaciones + disciplinas) |
| 50 miembros con productos | 50+ consultas | 2 consultas (relaciones + productos) |
| 50 miembros con todo | 150+ consultas | 6 consultas (3 relaciones + 3 entidades) |
El numero de consultas es constante independientemente de la cantidad de miembros.
Frontend (Perspectiva de Usuario)
Vistas
Las optimizaciones de cache y carga por lotes son transparentes para el usuario final. No existen vistas especificas de gestion de cache. Los beneficios se perciben como:
- Listados mas rapidos: Los listados de miembros cargan significativamente mas rapido
- Selectores de categoria rapidos: Los selectores de categoria en formularios responden casi instantaneamente
- Facturacion mas agil: La facturacion por lotes completa mas rapido al consultar datos optimizados
Interacciones del usuario
Las interacciones que invalidan el cache son transparentes:
- Crear/modificar/eliminar categoria: El cache se invalida automaticamente; la proxima consulta obtiene datos frescos
- Crear/modificar/eliminar disciplina: El cache se invalida automaticamente; la proxima consulta obtiene datos frescos
Estados de UI
No hay estados de UI especificos para el cache. Las mejoras de rendimiento se perciben como tiempos de carga reducidos en todas las vistas que consultan categorias, disciplinas o listados de miembros.
Backend (Perspectiva de Datos de Negocio)
Entidades de negocio involucradas
Cache de Categorias de Membresia
Almacenamiento temporal del listado de categorias de membresia por tenant.
| Dato de negocio | Descripcion |
|---|---|
| Tenant | Sucursal/caja a la que pertenecen los datos |
| Categorias | Listado de categorias de membresia con datos basicos |
| Tiempo de vida | Periodo de validez del cache (configurable) |
| Estado | Vigente o expirado |
Cache de Disciplinas
Almacenamiento temporal del listado de disciplinas por tenant.
| Dato de negocio | Descripcion |
|---|---|
| Tenant | Sucursal/caja a la que pertenecen los datos |
| Disciplinas | Listado de disciplinas con datos basicos |
| Tiempo de vida | Periodo de validez del cache (configurable) |
| Estado | Vigente o expirado |
Relaciones de negocio
- El cache esta aislado por tenant (sucursal/caja)
- Cada tenant tiene su propio espacio de cache para categorias y disciplinas
- La invalidacion es especifica por tipo de dato y tenant
- La carga por lotes agrupa consultas de relaciones miembro-entidad y entidades referenciadas
Validaciones de negocio
| Validacion | Descripcion |
|---|---|
| Aislamiento por tenant | Los datos cacheados de un tenant no son accesibles por otro |
| Invalidacion por operacion | Toda operacion de escritura invalida el cache correspondiente |
| Consistencia | Si el cache no esta disponible, los datos se obtienen de la base de datos |
| TTL respetado | Los datos expirados se recargan automaticamente |
Reglas de Negocio
RN-001: Cache solo para consultas simples
Descripcion: El cache de categorias y disciplinas solo se utiliza para consultas basicas sin opciones especiales. Las consultas con filtros, includes o alcance diferente a minimo siempre van a la base de datos.
Condicion: Se solicita un listado de categorias o disciplinas.
Accion:
- Si es consulta simple sin opciones y alcance minimo: servir desde cache (si disponible)
- En cualquier otro caso: consultar la base de datos directamente
RN-002: Invalidacion automatica en escritura
Descripcion: Toda operacion de creacion, modificacion o eliminacion de categorias o disciplinas invalida automaticamente el cache del tenant actual.
Condicion: Se crea, modifica o elimina una categoria o disciplina.
Accion:
- Ejecutar la operacion de escritura
- Invalidar el cache del tipo de dato afectado para el tenant actual
- Las proximas consultas recargaran los datos desde la base de datos
RN-003: Aislamiento estricto por tenant
Descripcion: El cache de cada tenant esta completamente aislado. Los datos cacheados de una sucursal no son accesibles ni afectan a otra sucursal.
Condicion: Se accede al cache desde cualquier operacion.
Accion:
- Identificar el tenant actual desde el contexto de la solicitud
- Acceder unicamente al espacio de cache del tenant identificado
- Las invalidaciones solo afectan al tenant actual
RN-004: Degradacion elegante sin cache
Descripcion: Si el cache no esta disponible (por fallo o expiracion), el sistema continua funcionando consultando la base de datos directamente. No se generan errores al usuario.
Condicion: El cache no esta disponible o los datos estan expirados.
Accion:
- Consultar la base de datos directamente
- Almacenar los nuevos resultados en cache para futuras consultas
- El usuario no percibe diferencia (solo un tiempo de respuesta ligeramente mayor)
RN-005: Consultas agrupadas para listados de miembros
Descripcion: Al cargar datos relacionados de multiples miembros, las consultas se agrupan por tipo de relacion en lugar de ejecutarse individualmente para cada miembro.
Condicion: Se solicita un listado de miembros con relaciones incluidas.
Accion:
- Recolectar los identificadores de todos los miembros del listado
- Ejecutar una consulta agrupada por cada tipo de relacion
- Ejecutar una consulta agrupada por cada tipo de entidad referenciada
- Mapear los resultados a cada miembro
Casos de Uso
CU-001: Consulta de categorias con cache vigente
Actor: Sistema (proceso interno)
Precondiciones:
- Existe cache vigente de categorias para el tenant actual
- Se solicita una consulta simple sin opciones especiales
Flujo principal:
- Se solicita el listado de categorias
- El sistema verifica que es una consulta simple sin opciones
- El sistema busca en el cache del tenant actual
- Los datos existen y estan vigentes
- Se devuelven los datos desde cache sin consultar la base de datos
Postcondiciones:
- Los datos se devuelven inmediatamente desde cache
- No se genera consulta a la base de datos
CU-002: Invalidacion de cache por modificacion
Actor: Usuario de Membresias
Precondiciones:
- Existe cache vigente de categorias para el tenant actual
- El usuario modifica una categoria
Flujo principal:
- El usuario modifica los datos de una categoria
- El sistema ejecuta la actualizacion en la base de datos
- El sistema invalida automaticamente el cache de categorias del tenant actual
- La proxima consulta de categorias recargara los datos desde la base de datos
Postcondiciones:
- La categoria esta modificada en la base de datos
- El cache de categorias del tenant esta invalidado
- Las proximas consultas obtendran datos actualizados
CU-003: Carga por lotes de un listado de miembros
Actor: Sistema (proceso de facturacion o consulta de listado)
Precondiciones:
- Se solicita un listado de 100 miembros con categorias, disciplinas y productos incluidos
Flujo principal:
- Se obtiene el listado de 100 miembros
- Se recolectan los 100 identificadores de miembros
- Se ejecuta 1 consulta para obtener todas las relaciones categoria-miembro
- Se ejecuta 1 consulta para obtener todas las relaciones disciplina-miembro
- Se ejecuta 1 consulta para obtener todas las relaciones producto-miembro
- Se identifican las categorias, disciplinas y productos unicos referenciados
- Se ejecuta 1 consulta para obtener todas las categorias referenciadas
- Se ejecuta 1 consulta para obtener todas las disciplinas referenciadas
- Se ejecuta 1 consulta para obtener todos los productos referenciados
- Se mapean los resultados a cada miembro
Postcondiciones:
- Los 100 miembros estan enriquecidos con sus relaciones
- Se ejecutaron solo 6 consultas agrupadas en lugar de 300+ individuales
Consideraciones
Seguridad
- El aislamiento por tenant del cache garantiza que no hay fuga de datos entre sucursales
- El cache no expone datos sensibles adicionales; contiene los mismos datos que la consulta directa
Auditoria
- Las operaciones de cache (lectura, escritura, invalidacion) no generan registros de auditoria
- Las operaciones de escritura que invalidan el cache SI son auditadas (la auditoría se registra por la operacion CRUD en si misma)
Rendimiento
- La carga desde cache es ordenes de magnitud mas rapida que la consulta a base de datos
- La carga por lotes reduce el numero de consultas de O(N) a O(1) por tipo de relacion
- El TTL del cache es configurable para balancear frescura vs rendimiento
- En operaciones masivas (facturacion de cientos de socios), ambas optimizaciones se combinan para un rendimiento optimo
Dependencias
Funcionalidades relacionadas
- Categorias de membresia: Datos maestros cacheados
- Disciplinas: Datos maestros cacheados
- Enriquecimiento de miembros: Consumidor principal de la carga por lotes
- Facturacion por lotes: Beneficiario principal de ambas optimizaciones
- Listado de miembros: Se beneficia de la carga por lotes en la consulta paginada
Criterios de Aceptacion
- [x] AC-001: Las categorias se sirven desde cache para consultas simples sin opciones
- [x] AC-002: Las disciplinas se sirven desde cache para consultas simples sin opciones
- [x] AC-003: El cache se invalida automaticamente al crear, modificar o eliminar categorias
- [x] AC-004: El cache se invalida automaticamente al crear, modificar o eliminar disciplinas
- [x] AC-005: El cache esta aislado por tenant (sucursal/caja)
- [x] AC-006: Si el cache no esta disponible, los datos se obtienen de la base de datos sin error
- [x] AC-007: Las consultas con opciones especiales no usan cache
- [x] AC-008: La carga por lotes obtiene relaciones de multiples miembros en consultas agrupadas
- [x] AC-009: La carga por lotes obtiene entidades referenciadas en consultas agrupadas
- [x] AC-010: El numero de consultas agrupadas es constante independientemente de la cantidad de miembros
Notas Adicionales
Relacion entre cache y carga por lotes
El cache y la carga por lotes son optimizaciones complementarias que operan en diferentes niveles:
- Cache: Optimiza la consulta repetida de datos maestros (categorias, disciplinas) que cambian con poca frecuencia
- Carga por lotes: Optimiza la consulta de datos relacionados (relaciones miembro-entidad) que dependen del listado actual
Ambos mecanismos se combinan: al cargar un listado de miembros con categorias, la carga por lotes agrupa las relaciones y luego las categorias individuales pueden servirse desde cache.
Historial de Cambios
| Fecha | Version | Autor | Descripcion |
|---|---|---|---|
| 2026-01-27 | 1.0 | Sistema | Documentacion de funcionalidad implementada |