Hay una vieja máxima en nuestra industria que dice que solo hay dos problemas difíciles en la informática: limpiar la caché y nombrar variables. Tras lidiar durante una década con sistemas de caché en ORMs tipo Doctrine, Hibernate o Prisma, puedo confirmar que el problema de la caché no es difícil; es una absoluta tortura.
Piensa en el flujo de trabajo estándar en la industria actual (el tan laureado "Best Practice"):
- Ejecutas un
User::find(1)->with('profile'). - Usas la librería de turno para guardar el resultado en Redis bajo la clave
user_profile_1durante una hora. - Dos minutos después, por otro recodo del ecosistema de tu app, el perfil de usuario se actualiza porque el usuario cambió su avatar.
- Tú, como desarrollador, tienes que acordarte (o crear un ruidoso "Event Listener" / "Observer") de inyectar un
Cache::forget('user_profile_1')justo en el Model.
Olvidas incluir el forget() en uno de los treinta microservicios... y voilà, tu sistema escupe el odioso Stale Data (Datos antiguos), y tienes a QA llenándote la bandeja del correo con reportes fantasma porque "la foto del usuario no se actualiza".
JUX Framework soluciona esto de una forma que hará santiguarse a los puristas del DDD (Domain Driven Design): Atacando por debajo del ORM, con interceptación de Lexer SQL puro.
1. El Proxy SQL: Memoria Bruta
Al abrir _classes_/cache.class.php (la venerable clase MyCache), vemos que JUX ignora a los modelos en sí (si es un Usuario, un Log o un Producto). JUX trabaja a nivel de base de datos interceptando consultas de sintaxis limpia. Puede funcionar con MemVar local, Ficheros, o conectarse directamente a Redis.
Cuando la tabla o módulo ejecuta un humilde SELECT * FROM auth_users WHERE ID = x, JUX calcula el Hash MD5 de esa cadena exacta. Si esa foto SQL ya existe en Redis, no molesta en despertar al disco duro de MySQL. Escupe la respuesta devuelta por el demonio en memoria y a correr.
De acuerdo. Eso no tiene mérito. Cualquiera sabe cachear un SELECT. La guerra comienza cuando alteras los datos (El temido Stale Data). Aquí es donde JUX me robó el corazón.
2. El Francotirador de SQL (getTableNameFromSql)
Cuando disparas una operación mutadora a tu capa de base de datos —ya sea un UPDATE, un INSERT, un DELETE o incluso un ALTER TABLE— la clase MyCache actúa como un vigía. En un framework pijo, aquí es donde tus Event Dispatchers estallarían.
JUX simplemente pasa el crudo String SQL que estás enviando por una función parseadora propia y bestial:
// JUX analiza palabras clave en bruto para deducir qué está pasando:
private static function getTableNameFromSql($sql) {
if (preg_match("/(UPDATE|INSERT INTO|DELETE FROM)\s+([a-zA-Z0-9_]+)/i", $sql, $matches)) {
return $matches[2]; // Bingo: ¡Tenemos la tabla!
}
// ... más heurística de sintaxis MySQL pura ...
}
La clase examina el texto. Lee la orden y concluye: "Aha. El usuario no está modificando la entidad ModelUser. El usuario le ha mandado a base de datos actualizar concretamente la tabla auth_users".
3. La Aniquilación de Cachés por Exceso de Celo ("Wildcard Kill")
Sabiendo que la tabla auth_users ha sido violada, JUX toma una decisión arquitectónica brutal que resuelve el mayor problema del Stale Data a martillazos de pragmatismo.
No busca exactamente el Hash SQL de ese usuario en concreto. Agarra y se comunica con el motor Redis de forma quirúrgica para ejecutar internamente un reseteo de prefijo (Wildcard Purge):
// JUX aniquila absolutamente todo rastro de esa tabla en la caché
$this->redis->deleteByPrefix($tableName . ':*');
Fin del problema de variables mal nombradas por humanos. ¿Modificaste el campo de un usuario a mano? JUX deduce que has tocado a los usuarios y bombardea los IDs de Redis asociados a esa tabla. Al milisegundo siguiente, cuando el Frontend pida de nuevo el perfil, no hay Hits de Caché antiguos; le tocará consultar a MySQL fresco la información prístina, llenando de nuevo Redis instantáneamente.
Conclusión: Tolerancia a Fallos vs Estética de Código
Para la doctrina académica, borrar por completo 30 registros en Redis porque se actualizó uno solo de ellos es ineficiente; prefieren la engorrosa inyección de dependencias para calcular las etiquetas concretas en cada controlador de la aplicación.
¿Qué opina un Senior curtido en proyectos estancados de doce meses? Que la técnica de JUX es oro puro. El milisegundo extra que tarda MySQL en repoblar la caché de un par de registros no es **absolutamente nada** comparado cont el cero por ciento (0%) de esfuerzo cerebral y de mantenimiento que exige a un desarrollador lidiar con los tags de un ORM.
En JUX, escribes SQL. JUX lo cachea, JUX lo destruye cuando él nota que lo has alterado. Y tú vuelves a casa en hora a ver una serie sin preocuparte del "Invalidate State".
En el próximo capítulo de esta inmersión, me ceñiré el casco de trinchera y desmontaré la madre de todas las bestias: La Máquina de Estados Finita Table. Un generador DataGrid y Forms de 2.400 líneas que te borra de la mente la necesidad de descargar una plantilla AdminLTE de Internet.
Nos vemos en el próximo bloque de funciones.