Check diario de frescura de raw.*

Reemplaza a DVT (deprecado el mismo día): un check mucho más chico a propósito — un solo script Python, sin contenedor propio, que compara solo el número de filas modificadas en los últimos 30 días entre cada tabla de raw.* en Postgres y su fuente real en .207 (ver Conexiones a TRIVASADB). No valida columnas ni schema — ese alcance era justo lo que hacía pesado a DVT (imagen Docker propia, mapping de columnas, dos herramientas de comparación distintas). Este check cubre la pregunta que de verdad importa día a día: ¿la carga de esta mañana trajo lo que debía traer, o algo se quedó atrás?

Por qué 30 días y fecha_ult_modif

Las 15 tablas de raw.* comparten una columna de auditoría — fecha_ult_modif en Postgres, Fecha_Ult_Modif en .207 — que es la misma que ya usan los pipelines de dlt como cursor incremental. Reusarla para el check evita inventar un criterio nuevo: si dlt confía en esa columna para saber qué sincronizar, el check confía en ella para saber qué comparar. Filtrar a los últimos 30 días evita escanear el histórico completo en tablas grandes (movimiento tiene 4.5M+ filas totales) para un chequeo que solo necesita confirmar que lo reciente está al día.

Tolerancia: por qué no es una comparación exacta

.207 es la base operativa en vivo — sigue recibiendo escrituras entre que corre el último sync de dlt (6:45 AM) y el momento en que corre este check (7:00 AM). Una diferencia de un puñado de filas ahí es lag normal, no una falla real (mismo criterio que ya usaba DVT con su --threshold, y que documenta Warehouse Postgres § verificación). Umbral: max(5, 0.1% del conteo en la fuente) — por debajo, warn; por encima, fail.

Corrida fuera de horario, diffs grandes son esperados: una prueba manual corrida a mitad del día (varias horas después del sync de las 6:45 AM, con producción activa todo ese tiempo) va a mostrar diffs de cientos o miles de filas en tablas de alto volumen como movimiento — no es un bug del check, es exactamente lo que debe detectar. La corrida real de cron ocurre 15 minutos después de la última carga, cuando el hueco esperado es mínimo.

Cron

0 7 * * * cd ~/trivasa-bi-dev/raw-checks && venv/bin/python3 check_raw_freshness.py

7:00 AM UTC (1:00 AM hora local Mexico) — mismo horario que usaba DVT, 15 minutos después de que termina el último de los 4 crons de pipelines dlt (6:45 AM, movimiento).

Dashboard en Perses

https://data.frento.com.mx, proyecto soda, dashboard “Soda Data Quality (real)” (job="soda_real") — existía diseñado desde un intento anterior con Soda Core (ver “Por qué se reemplazó Soda Core” en DVT) pero nunca llegó a desplegarse; se revivió y se le agregaron 2 paneles nuevos para esta ocasión:

  • Los 3 stats + barras apiladas que ya traía (fails/warnings totales, health score, checks por outcome y día).
  • Fallos/warnings por tabla — qué tabla específica de raw.* está desfasada, sin saturar la vista con las que están en pass.
  • Diferencia de filas por tabla — el valor numérico real (fuente − destino) en el tiempo, vía unwrap de LogQL sobre el campo diff del JSON posteado a Loki, no solo el veredicto pass/warn/fail.

Los otros dos dashboards del mismo proyecto Perses (dvt-data-quality, data-health-status, job="dvt") quedan sin datos nuevos desde que DVT se decomisionó — no se borraron ni se re-apuntaron, simplemente van a mostrar “sin datos” indefinidamente a menos que algo vuelva a postear con ese job.

Sin notificación activa — decisión deliberada

El script no manda alertas a ningún canal externo (Telegram, email) si sale en fail — evaluado y descartado el 2026-08-10: no justificaba montar un bot o webhook dedicado solo para esto. En su lugar, dos cosas baratas para que revisar el estado de hoy no implique leer el log completo:

  • Banner al final del output (✅ PASS / ⚠️ WARN / ❌ FAIL + conteo), lo último que se ve con tail del log de cron.
  • last_status.txt (mismo directorio que el script) — se sobreescribe en cada corrida con el resultado y el detalle de cualquier tabla que no esté en pass. cat ~/trivasa-bi-dev/raw-checks/last_status.txt es la forma rápida de saber si hoy hubo problema, sin abrir Perses ni el log.

El dashboard de Perses sigue siendo la fuente de verdad para tendencia en el tiempo; esto es solo para el chequeo del día a día.

Retención en MinIO (relacionado, no de este check)

El bucket lightdash de MinIO (donde caen las capturas del carrusel de dashboards) no tenía ninguna regla de expiración — crecía sin límite con cada render horario de los 3 schedulers. Se agregó una regla de ciclo de vida el mismo día:

docker exec lightdash-minio mc ilm add --expire-days 7 local/lightdash

Objetos de más de 7 días se borran solos (MinIO lo evalúa en un scan periódico, no al instante). No relacionado al check de frescura de raw.* más allá de haberse revisado en la misma sesión de mantenimiento.

Véase también