mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 16:33:18 +00:00
Fase 5 (migracion de datos): - api/scripts/migrate-sqlite-to-postgres.ts: ETL unico SQLite -> Postgres. Pre-flight (CURP/RFC duplicados case-insensitive, FKs huerfanas, tenant_id invalido, fechas mal formateadas) -> carga por base/esquema con credenciales _owner (setval de secuencias, OVERRIDING SYSTEM VALUE, ON CONFLICT DO NOTHING idempotente) -> verificacion de conteos y sumas de dinero con tolerancia. Probado end-to-end contra un dataset SQLite legacy sintetico y un Postgres limpio (solo schema+catalogos, sin contexto dev): 100% de las filas migradas, sumas de dinero exactas, snapshot de uploaded_by/created_by resuelto correctamente. - db/RUNBOOK-corte.md: checklist go/no-go para el corte por ambiente. - Fix de bug real encontrado al probar: sin --context-filter explicito, Liquibase corre TAMBIEN los changesets context=dev (comportamiento por defecto, no "modo seguro") -- documentado en db/README.md con el ejemplo correcto (--context-filter='!dev' para staging/produccion). Fase 5b: patron de compensacion para createTenant ya resuelto en el rewrite de saas.ts (fase 3/4). Fase 6 (backups): db/backups/ con plantillas pgBackRest por base, politica de retencion, nota de persistencia minima de Redis (RDB, sin retencion de negocio), checklist de simulacro de restauracion mensual, y la validacion pendiente de si Coolify permite WAL archiving antes de comprometerse a PITR real. Fase 7 (limpieza y CI): - Dockerfile.api simplificado (sin JRE/Liquibase/FFI). Dockerfile.migrate y Dockerfile.provision nuevos, de un solo uso, para el paso explicito de deploy (nunca sirven trafico). - docker-compose.yml: postgres+redis+provision+migrate para dev local end-to-end; api ya no arranca hasta que migrate termina bien. - docs/coolify.md y .env.example actualizados al modelo de 2 bases + Redis + Contabo. - api/schema.sql eliminado (desincronizado, competia con Liquibase como fuente de verdad). - .github/workflows/ci.yml: Postgres+Redis de servicio, aprovisiona roles/ACLs, dry-run de Liquibase (updateSQL) antes de aplicar, verify-isolation.sh, deno check + deno test, build de los dos frontends. Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
89 lines
3.8 KiB
Markdown
89 lines
3.8 KiB
Markdown
# Runbook de corte SQLite → Postgres (Fase 5)
|
|
|
|
Checklist operativo para migrar UN ambiente (dev, luego staging, luego
|
|
producción -- nunca saltar directo a producción). Usa
|
|
[`api/scripts/migrate-sqlite-to-postgres.ts`](../api/scripts/migrate-sqlite-to-postgres.ts).
|
|
|
|
## 0. Antes de empezar
|
|
|
|
- [ ] Postgres del ambiente aprovisionado (`db/provision/`) y migrado
|
|
**sin** datos de demo: `./db/update.sh all --context-filter='!dev'`.
|
|
- [ ] Backup fresco del volumen SQLite actual (`data/app.db`, `data/platform.db`)
|
|
guardado aparte, fuera del volumen que se va a apagar.
|
|
- [ ] Credenciales `_owner` de los 3 módulos disponibles en el entorno
|
|
(`DATABASE_URL_PLATFORM_OWNER`, `DATABASE_URL_IAM_OWNER`, `DATABASE_URL_CORE_OWNER`).
|
|
|
|
## 1. Pre-flight (sin ventana de mantenimiento, se puede correr en caliente)
|
|
|
|
```bash
|
|
cd api
|
|
deno run --allow-ffi --allow-net --allow-read --allow-write --allow-env \
|
|
scripts/migrate-sqlite-to-postgres.ts --dry-run \
|
|
--app-db=../data/app.db --platform-db=../data/platform.db
|
|
```
|
|
|
|
Si el pre-flight reporta `[FAIL]`, **no continuar** -- corregir los datos
|
|
en SQLite (duplicados, huérfanas, tenant_id inválido, fechas mal
|
|
formateadas) y repetir hasta que todo salga `[OK]`.
|
|
|
|
## 2. Ventana de mantenimiento (corte real)
|
|
|
|
Hoy no existe un "modo mantenimiento" en la app. Opciones, de menor a
|
|
mayor invasividad:
|
|
|
|
- Parar el contenedor/proceso `api` (nadie puede escribir mientras está
|
|
abajo -- los fronts mostrarán error de conexión).
|
|
- Responder 503 temporal en nginx para `/v1/*` mientras se corre el ETL.
|
|
|
|
Elegir una, documentar la hora exacta de inicio.
|
|
|
|
## 3. Migración
|
|
|
|
```bash
|
|
cd api
|
|
set -a && source /ruta/al/.env.del.ambiente && set +a
|
|
deno run --allow-ffi --allow-net --allow-read --allow-write --allow-env \
|
|
scripts/migrate-sqlite-to-postgres.ts \
|
|
--app-db=/ruta/a/app.db --platform-db=/ruta/a/platform.db
|
|
```
|
|
|
|
El script hace: pre-flight → carga (una transacción por base/esquema,
|
|
todo o nada) → `setval()` de secuencias → verificación de conteos y sumas
|
|
de dinero. Si CUALQUIER paso falla, no queda un estado a medias en
|
|
Postgres (la transacción de esa base se revierte completa), pero SQLite
|
|
sigue siendo la fuente de verdad -- no se ha cortado nada todavía.
|
|
|
|
## 4. Criterios go/no-go
|
|
|
|
Antes de apuntar la app a Postgres y apagar SQLite:
|
|
|
|
- [ ] El script terminó con `Migración completa y verificada.` (exit code 0).
|
|
- [ ] Conteos de filas origen=destino en **todas** las tablas listadas
|
|
(no solo las 9 de ejemplo del script -- ampliar `verifyCounts()` si
|
|
el ambiente tiene datos en tablas no cubiertas ahí).
|
|
- [ ] Diferencia de sumas de dinero dentro de la tolerancia ($0.05) -- si
|
|
no cuadra, decidir explícitamente si se acepta el redondeo
|
|
REAL→NUMERIC o se investiga antes de continuar.
|
|
- [ ] Spot-check manual de 2-3 registros conocidos (un trabajador, un
|
|
preupuesto, un préstamo) comparando app vieja vs. Postgres.
|
|
|
|
Si algo no cuadra: **no cortar**. Volver a levantar la app contra SQLite
|
|
(no se tocó), investigar, y repetir desde el paso 1 en otro intento.
|
|
|
|
## 5. Cutover
|
|
|
|
- [ ] Actualizar `DATABASE_URL_*`/`REDIS_URL_*` del servicio `api` a los
|
|
valores del ambiente Postgres/Redis recién migrado.
|
|
- [ ] Levantar `api` -- el fail-fast de arranque (`/v1/health`) debe
|
|
responder `{"ok":true,...}` antes de reabrir tráfico.
|
|
- [ ] Reabrir tráfico (quitar el 503/levantar el contenedor).
|
|
- [ ] Login de prueba con un usuario real del ambiente.
|
|
|
|
## 6. Después del corte
|
|
|
|
- [ ] Conservar el volumen SQLite (`data/`) como respaldo frío por un
|
|
período de retención definido (ej. 30 días) antes de borrarlo.
|
|
- [ ] Correr `./db/provision/verify-isolation.sh` contra el ambiente para
|
|
confirmar que el aislamiento de roles/RLS/ACLs sigue intacto.
|
|
- [ ] Repetir todo el runbook en el siguiente ambiente (dev → staging →
|
|
producción), nunca en paralelo.
|