Instruction file imported from SleyiW/iWana-neXt (
.github/instructions/database.instructions.md). Copyright stays with the author.
Database and Tenancy Instructions
Referencia maestra: AGENTS.md.
packages/databasees la fuente de verdad para DataSource, entidades, contexto de tenant y migraciones versionadas.- Distinguir siempre entre migraciones de
publicy migraciones detenant; no mezclar responsabilidades. - Para schemas tenant, validar nombres antes de interpolarlos y usar helpers aprobados como
runInTenantSchema(). - Las migraciones de tenant deben ser idempotentes cuando el flujo operativo lo requiera y dejar manejo claro de fallos parciales.
- En migraciones tenant, registrar resultado por schema y fallar el proceso completo si hay fallos parciales; no dejar errores silenciosos.
- Al agregar una nueva migracion ejecutable por CLI, mantener sincronizados los scripts de
package.jsono el punto de entrada operativo para evitar que el runner siga apuntando a una migracion anterior. - Usar
IF NOT EXISTSo estrategia equivalente cuando la migracion retroactiva de tenant deba tolerar reintentos operativos. - Mantener el patron de
main()con importacion dinamica del DataSource cuando el script de migracion se ejecute directamente desdedist. - Mantener comentarios en espanol cuando la logica de migracion, tenancy o seguridad de datos no sea trivial.
- Antes de proponer cambios de persistencia, revisar entidades,
data-source.ts, migraciones existentes y ADRs aplicables.
Flag transactional (ADR-066)
El runner/revert tenant (migrations/tenant/runner.ts, revert.ts) envuelve cada migración en una transacción por defecto (transactional ?? true). Para DDL que PostgreSQL prohíbe dentro de TX (CREATE INDEX CONCURRENTLY, DROP INDEX CONCURRENTLY, REINDEX CONCURRENTLY, etc.):
- Declarar en la clase de migración:
transactional = false. - El runner ejecuta
up()/down()fuera de transacción e inserta/elimina el bookkeeping entypeorm_migrationsen una TX aparte. - Idempotencia obligatoria:
up()conIF NOT EXISTS/down()conIF EXISTS(reintento seguro si el bookkeeping falla tras el DDL). - Sin DML en la misma migración no transaccional. Si hace falta DML + índices CONCURRENTLY, separar en dos migraciones (transaccional + no transaccional).
- TypeORM nativo expone
transactionenMigrationInterface; el runner tenant leetransactional(contrato ADR-066), no el flag nativo del CLI. - Default
true: las migraciones 000–086 y cualquier otra sin el flag siguen el camino atómico actual. - Un fallo en camino no transaccional no garantiza atomicidad DDL↔registro; el mensaje de error pide verificar el schema a mano.