ADR: Data Warehouse Epilogue en el orquestador
Aceptada (2026-06-03). Implementada vía SDD migracion-segura-orquestador
(PR #59, archive Engram #1352). Cierra esta ADR que estaba pendiente en
Indice-ADRs desde 2026-05-18.
Contexto
Sección titulada «Contexto»El orquestador run_pipeline.py corría los pipelines y publicaba a Google Sheets
(--publish), pero el build del Data Warehouse (data_warehouse.py --populate) y
la migración a Supabase eran pasos MANUALES aparte — no participaban en el flujo
del orquestador. Consecuencias:
- Tras una corrida diaria, el DW y el Power BI del cliente quedaban desactualizados hasta que alguien corría los scripts a mano.
dim_ot—dimensión central del star schema— ni siquiera se construía en--populate(vivía huérfano enscripts/generate_dim_ot.py).migrate_all.pytenía un footgun: borraba por default del destino toda tabla no incluida en los MAPPINGS del source → unmigrate_all --source data_warehousehabría borradodim_otde Supabase (ver el cambio que acompaña esta ADR).
Opciones evaluadas
Sección titulada «Opciones evaluadas»Opción A — Mantener manual (status quo)
Sección titulada «Opción A — Mantener manual (status quo)»Seguir corriendo data_warehouse.py --populate + migrate_all.py a mano tras los pipelines.
Descartada: se olvida; el Power BI queda desactualizado; no hay garantía de orden (pipelines → DW → migración).
Opción B — Epílogo opt-in en el orquestador (ELEGIDA)
Sección titulada «Opción B — Epílogo opt-in en el orquestador (ELEGIDA)»Un flag explícito --migrate en run_pipeline.py que, tras un --all exitoso,
construye el DW completo y migra de forma segura.
Elegida porque: un solo comando hace el flujo end-to-end; el orden queda garantizado; es opt-in (no cambia el comportamiento por default); el gate “todos los pipelines OK” evita migrar datos parciales.
Opción C — Cron/scheduler separado
Sección titulada «Opción C — Cron/scheduler separado»Un job programado independiente que orqueste DW + migración.
Descartada: más infraestructura; menos cohesión con la corrida real; duplica la lógica de “cuándo es seguro migrar”.
Decisión
Sección titulada «Decisión»Opción B. Características del epílogo --migrate:
| Aspecto | Decisión |
|---|---|
| Activación | Flag explícito --migrate, solo válido con --all (sin —all → error) |
| Gate | Migra solo si TODOS los pipelines terminaron success; si uno falla → omitido, “Supabase intacto” |
| Invocación | In-process (import + funciones reusables populate() / run_migration()), no subprocess — mejor testabilidad y acoplamiento, alineado con el framework v2 |
| Destinos | Factory get_default_destinations() — desacopla el orquestador del dict DESTINATIONS |
| Seguridad de drop | compute_tables_to_drop (función pura): borra tablas ajenas solo con --full-wipe explícito; default = no borra nada |
| Señal de fallo | Si el epílogo falla (excepción o sin destinos) → exit ≠ 0 (no enmascara fallos de sync en runs automatizados) |
dim_ot | Se construye en --populate (export_dim_ot, build_dim_ot puro) y queda en MAPPINGS_DATA_WAREHOUSE |
run_pipeline.py --all --migrate pipelines (ingest→...→publish GSheets) │ (todos OK) ▼ populate() → construye data_warehouse.db (incl. dim_ot) │ run_migration() → migra seguro (drop opt-in) con destinos reales ▼ Supabase → Power BIConsecuencias
Sección titulada «Consecuencias»Positivas
Sección titulada «Positivas»- Flujo end-to-end con un solo comando; orden garantizado.
- Seguro por default: nunca borra tablas vivas sin
--full-wipe. dim_otdeja de ser huérfano (en--populate+ en MAPPINGS).- Fallos de migración ya no pasan desapercibidos (exit ≠ 0).
Negativas
Sección titulada «Negativas»- Acopla el orquestador a la capa DW/migración — mitigado con funciones reusables
(
populate,run_migration) y la factoryget_default_destinations.
Neutras
Sección titulada «Neutras»- La migración real sigue siendo opt-in: para refresh ad-hoc, los scripts standalone
(
data_warehouse.py --populate,migrate_all.py) siguen disponibles.
Lección (del ciclo SDD)
Sección titulada «Lección (del ciclo SDD)»El primer verify dio FAIL: el epílogo pasaba destinations=[] a run_migration
→ un no-op silencioso que testeaba verde pero nunca migraba. Se corrigió con la
factory de destinos reales + un test que valida destinos no-vacíos. Lección: un feature
de integración necesita verificación con ejecución real que pruebe el efecto, no solo
que las funciones se invoquen.
Ver también
Sección titulada «Ver también»- ADR-Source-Connectors — patrón Hexagonal para fuentes (cara opuesta: sinks)
- ADR-Integracion-Alertas-Waypoint-DW — el cambio previo que destapó el footgun de migración
- Reference-BasePipeline — framework del orquestador
- Indice-ADRs — registro de decisiones
- Código:
run_pipeline.py(epílogo),migrate_all.py,scripts/db/migrate_utils.py,scripts/db/data_warehouse.py,domains/dim_ot/build_dim_ot.py - Specs:
openspec/specs/data-migration/spec.md(NEW) +data-warehouse/pipelines(delta)