diff --git a/OPTIMIZACION_CACHE.md b/OPTIMIZACION_CACHE.md deleted file mode 100644 index a9603b5..0000000 --- a/OPTIMIZACION_CACHE.md +++ /dev/null @@ -1,78 +0,0 @@ -# OPTIMIZACIÓN — Caché de descargas pesadas (reutilizable en Ventas, Comisiones, etc.) - -## El problema (síntoma) -Al cambiar un filtro (mes, sede, etc.) el dashboard se demora 15-130 segundos, -aunque los datos "ya deberían estar cargados". Se siente como si cada filtro -volviera a descargar todo desde cero. - -## La causa raíz -Una función que **descarga datos de una fuente externa** (Supabase, SQL Server, -Postgre, API) se llama SIN caché. Cada vez que el usuario filtra, esa función -**vuelve a descargar TODO** desde internet. - -En LEADS el culpable fue `traer_cartera_rows()` (bajaba 86,000 filas de Supabase -de 1000 en 1000 = 86 pedidos en serie ≈ 52-130s) y se re-descargaba en CADA -cambio de mes, porque `matriz_web_formulario` la llamaba directo: - -```python -# ANTES (malo): re-descarga en cada llamada -def _load(): - rows = get_dm().traer_cartera_rows() # baja 86k filas CADA vez - ... -``` - -## Cómo diagnosticarlo (script de tiempos) -Medir cada parte por separado para encontrar QUÉ tarda. Clave: medir un cambio -de mes CON los insumos ya cargados (2a vez). Si sigue lento, algo se re-descarga. - -```python -import time, services as S -def cron(label, fn): - t0 = time.time(); fn(); print(f" {label:38} {time.time()-t0:6.1f}s") - -cron("dashboard MES1 (1a vez)", lambda: S.mi_funcion("2026","1",...)) -cron("dashboard MES2 (2a vez)", lambda: S.mi_funcion("2026","2",...)) # <-- debe ser rapido -# Si MES2 sale lento, desglosar: medir cada traer_* y cada matriz por separado -# hasta ver cual linea se lleva los segundos (casi siempre un traer_* sin cache). -``` - -## La solución (2 líneas, NO toca lógica ni resultados) -Envolver la descarga pesada en `cache_get_or_set` con clave GLOBAL, y que TODAS -las funciones usen ese helper cacheado en vez de descargar directo. - -```python -# 1) Helper cacheado (se baja UNA vez, se reutiliza) -def _cartera_rows_cache(): - return cache_get_or_set("cartera_rows", ("GLOBAL",), - lambda: get_dm().traer_cartera_rows()) - -# 2) Reemplazar TODAS las llamadas directas: -# get_dm().traer_cartera_rows() -> _cartera_rows_cache() -``` - -Resultado en LEADS: -- Cambiar de mes: de 69-133s -> 0.4s (solo filtra lo que ya está en memoria) -- La descarga pesada solo se paga 1 vez (en la precarga de arranque, en background). - -## Regla general para CUALQUIER dashboard (Ventas, Comisiones, Rentabilidad...) -1. Toda función `traer_*` / consulta a SQL/Supabase/API que se use en varias - vistas o en cada filtro, debe estar cacheada con `cache_get_or_set`. -2. NUNCA llamar `get_dm().traer_xxx()` directo dentro de un `_load` que depende - de filtros; usar el helper cacheado. -3. El filtro (mes/sede/programa) debe operar sobre datos YA en memoria, no - re-descargar. Filtrar en memoria = milisegundos. -4. Precargar en segundo plano (hilo daemon al startup) el mes actual/anterior - para que el usuario no espere la 1a carga. -5. El refresco periódico (cada 15 min) invalida caché -> considerar bajar datos - que cambian 1 vez al día (ej. cartera) con menos frecuencia, o recargar en - background sin dejar hueco. - -## Mejora opcional pendiente (no aplicada aún) -La 1a descarga de la cartera es lenta (100-155s) porque pagina de 1000 en 1000. -Subir el tamaño de lote (ej. limit=10000) reduce los viajes: de ~155s a ~10-15s. -Aplica a cualquier tabla grande que se baje paginada. - -## Verificación (que no cambien números) -Antes de optimizar, guardar una "línea base" con los totales actuales -(diag_base.json). Tras optimizar, comparar: deben ser IDÉNTICOS. La optimización -solo cambia CUÁNDO/CÓMO se descarga, nunca el cálculo.