basquetWi + New ticket
movilba MOVILBA-486

El import crea vehiculos y vdc una sola vez: salvo estado_id, ninguna columna de vdc se re-deriva nunca contra un snapshot mas nuevo

Done urgent cmcoder03-mba-l-cc

Medido 2026-09-18 contra pg_proc.prosrc en PROD (cuerpo instalado), coder03 y db02 por separado. rutap.materializar_snapshot_raices hace INSERT ... WHERE NOT EXISTS en public.vehiculos y en public.vehiculos_datos_colectivos: crea si falta, y si la fila ya existe no escribe nada. rutap.proyectar_snapshot escribe unicamente rutap.vehiculo_historial_normalizado; lee vdc y no la escribe. rutap.reconciliar_estado_abierto_snapshot es el unico UPDATE rutinario sobre vdc y setea una sola columna, estado_id. Consecuencia: toda columna de contenido de vdc salvo estado_id queda congelada al valor del primer write, sin importar cuantos snapshots correctos importen despues; cada correccion historica (091-cascade, 124-estandar-emisiones, 435, MOBAAPI-614) fue una migracion one-off a mano. Es la causa de fondo de MOVILBA-482, no un accidente de 3 filas. El modelo que enuncia Elazar (truncate vehiculos+vdc e importar del snapshot mas reciente) no esta implementado en ningun lado. Decision de producto para Elazar: si el import debe re-derivar vdc por snapshot, es un cambio de contrato del importador, no un parche.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 4w ago
  • wi-cli-venus note · 4w ago
    Blocker re-medido en PROD hoy (pg_constraint/pg_trigger), no tomado de la nota de otro carril. Tres FK entrantes a public.vehiculos, todas condeferrable=f: validadoras_historial_vehiculo_id_fkey (confdeltype r), vehiculos_datos_colectivos_vehiculo_id_fkey (a), rutap.vehiculo_historial_normalizado_vehiculo_id_fkey (a) - un TRUNCATE fisico exige CASCADE. Y trg_soft_delete_vehiculos + trg_soft_delete_vehiculos_datos_colectivos son BEFORE DELETE -> fn_soft_delete(), asi que un rebuild por DELETE se convierte en soft-delete silencioso. Los dos bloqueos son SEPARADOS: TRUNCATE no dispara triggers de fila (lo frenan las FK), DELETE si (lo frenan los triggers). CORRECCION a la lista del 09-04 (MOVILBA-227): rendiciones.deudas_dominios NO existe en PROD - to_regclass NULL en rendiciones y en public, y information_schema no tiene ninguna tabla que matchee %deuda%. Son tres FK, no cuatro. ADICION: rutap.vehiculo_historial_normalizado tiene vh_norm_reject_book_column_update, BEFORE UPDATE WHEN (old.rutap_snapshot_id IS NOT NULL), que rechaza de plano un rebuild por UPDATE-de-todas-las-columnas sobre cualquier fila venida de un snapshot; esa opcion solo queda abierta sobre vehiculos/vdc. Decision de Elazar, no de los carriles.
  • wi-cli-venus note · 4w ago
    CORRECCION al alcance de este item. Elazar disputo el veredicto 'no hay mecanismo' con un flujo observado en DEV (exporta Descargar, lo diffea contra el libro, arregla el importador, reimporta, y los valores RECONCILIAN sobre filas existentes). Tenia razon: existe un reconciliador, solo que no esta en el pipeline instalado. Es docs/migrations/2026-09-16-movilba-441-clean-baseline-loader-DEV.sql, cabecera 'Canonical DEV projector', descendiente committeado del dry-run de 227: UPDATE id-preservante de vehiculos y vdc sobre toda columna respaldada por el libro, mas INSERT solo para los vehiculo_id sin fila vdc viva, con COMMIT bajo \if :apply y ROLLBACK por default. Se corre a mano con -v apply=true. Confirmado independientemente por el archive de DEV, sin leer codigo: rafagas de UPDATE de 3037 el 2026-09-04 y 2388 el 2026-09-16 contra ~2400 filas vdc vivas, y una corrida con ROLLBACK no deja filas de archivo porque el insert del trigger se va con ella, asi que esas rafagas son applies committeados. El set de rutinas instaladas de DEV es identico al de PROD (4) y materializar no tiene ON CONFLICT ni UPDATE de vdc, asi que la reconciliacion no sale de una funcion instalada en ningun entorno. DEFECTO PRECISO, mas importante que el miss: casi toda columna es coalesce(s.X, d.X), es decir sobrescribe solo cuando el LIBRO trae valor; solo estado_id y fecha_vigencia_hasta son incondicionales. Un campo que el libro deja en blanco NO limpia nunca un valor viejo de la base. Contra 'MovilBA debe igualar al libro ni de mas ni de menos', un loader que solo puede agregar o sobrescribir y nunca borrar es un hueco de fidelidad. Ademas esta clavado a UN snapshot por archivo+md5+filas con RAISE EXCEPTION si falta, asi que no es un paso rutinario: hay que reescribirlo por snapshot. El veredicto anterior del item ('nada reescribe contenido de vdc') vale solo para el PIPELINE INSTALADO, no para el flujo del operador.
  • wi-cli-venus completed · 4w ago
    APLICADO en DEV y PROD 2026-09-18. Verificado ahora contra el cuerpo instalado en PROD (pg_proc.prosrc, no el repo): los dos chequeos de existencia de rutap.materializar_snapshot_raices quedaron SIN el predicado de estado - 'NOT EXISTS (SELECT 1 FROM public.vehiculos v WHERE upper(regexp_replace(...))=s.dominio_n)' y 'NOT EXISTS (SELECT 1 FROM vehiculos_datos_colectivos d WHERE d.vehiculo_id=v.id)'. Ya no puede fabricar un duplicado por no ver una fila marcada. OJO al re-verificar: un ILIKE '%NOT EXISTS%borrado_en IS NULL%' sobre el cuerpo da TRUE por falso positivo (engancha el NOT EXISTS de la linea 29 contra un borrado_en de 100 lineas mas abajo); hay que leer el texto alrededor de cada chequeo. Aplicacion: DEV borro 20 vehiculos + 17 vdc (la seccion 7 se vio disparar), PROD fue UPDATE puro (907+1140, cero ausentes).
bug
4w ago by wi-cli-venus
4w ago
2026-09-18 15:00