Published

⭐⭐⭐ N·4 · EL RÉGIMEN DE NAMESPACE — un inquilino, un entorno, un nivel

Connect any source, model it as an ontology, transform it, and operationalize it, analytics, automation and machine learning, under one governed, self-hostable roof. --- Most teams stitch the...

⭐⭐⭐ N·4 · EL RÉGIMEN DE NAMESPACE — un inquilino, un entorno, un nivel

Qué cierra: seis formas de nombrar conviviendo sobre las mismas tablas.
Estado: 🏁 CERRADO — datos consolidados · código desplegado y sirviendo · trinquete verde.

Regla de la casa: cada hecho lleva el comando que lo demuestra.


1 · El régimen

warehouse  w_<tenant>   ›   namespace  {env}   ›   tabla  ds_<hex>
  el inquilino, una vez      el entorno, una vez     la identidad física

⭐⭐⭐ El inquilino ya era el warehouse, y nadie lo había dicho. Medido: 2 de 2 workspaces tienen warehouse propio upstream (w_<hex>), que es el prefix de Iceberg REST — y ése es el mecanismo de multi-tenencia del estándar: Polaris pone un catálogo por inquilino, Unity Catalog un metastore/catálogo, Lakekeeper project→warehouse.

⇒ Escribir w_<tenant> también dentro del namespace decía el inquilino dos veces. Eso hacían prod.w_<hex> y prod_w_<hex>. La consolidación no promueve al inquilino: le quita la repetición, porque ya estaba arriba.

⚠️ Por qué el entorno se queda en el namespace

Lo suyo sería un warehouse por entorno. No se puede: la API de gestión de Gravitino responde 404 (medido en /api/metalakes y /api/metalakes/carbon/catalogs), así que no hay forma de crear uno. test y prod comparten warehouse y el namespace es lo único que los separa — quitarlo de ahí los haría colisionar.

⛔⛔ Y sigue siendo UN SOLO NIVEL

El punto lo hacía multinivel, que es lo que impedía NACER: Gravitino lo aplana y devuelve 500 con la tabla ya creada. Con un nivel, createTable responde 200 en 0,8 s.


2 · De dónde se venía

régimentablas
main.default83
prod.w_<hex>12
main.test9
prod_w_<hex>2
karma.test2
total108 vivas + 2 fantasmas

Ninguno estaba mal a propósito: cada uno fue el bueno en su momento y se quedó porque el namespace se PINEA por tabla. Nadie los eligió — se acumularon. Ésa es la deriva que un documento no para: no hay un commit que la introduzca, hay ciento ocho tablas nacidas en fechas distintas.


3 · Cómo se migró — y por qué así

renameTable en lote. Es lo único que da el estándar: Iceberg REST tiene renameTable/renameView pero no renameNamespace (apache/iceberg#13023, abierta), y Unity Catalog tampoco renombra un catálogo — obliga a crear el destino y mover los activos. No mueve bytes: sólo el puntero de metadata.

# ensayo (no toca nada)
N4_DESTINO=prod npx dotenv -e .env.local -- npx tsx scripts/warehouse/n4-1-consolidar-regimenes.ts
# de verdad
N4_DESTINO=prod npx dotenv -e .env.local -- npx tsx scripts/warehouse/n4-1-consolidar-regimenes.ts --aplicar --reconciliar-fantasmas
# el trinquete
npm run check:regimen-namespace

Las tres decisiones que sostienen la migración

① El destino es un PARÁMETRO, nunca LAKEHOUSE_ENV. La máquina que corre el script tiene LAKEHOUSE_ENV=test; derivarlo habría metido 108 tablas de producción en el namespace de desarrollo, y el pin es permanente. Un destino que se adivina es un destino que algún día se adivina mal.

② Compensación POR TABLA. Cada tabla son dos escrituras en dos sistemas —el rename en el catálogo y el pin en Index—. Si la segunda falla, la tabla existe donde Index no la busca: invisible, y no por estar rota. ⇒ se deshace el rename y se para. Y si la vuelta atrás también falla, se para gritando con la coordenada exacta.

③ ⛔⛔ TRES estados en el censo, no dos. Dos corridas seguidas dieron 107/3 y 108/2: un timeout de red se estaba contando como fantasma. Un censo que no distingue «no está» de «no pude preguntar» deja tablas atrás en silencio. ⇒ un fallo de transporte es indeterminado, se reintenta, y si sigue sin saberse se aborta la migración entera: mover un conjunto que no se ha podido censar es moverlo a ciegas.

⭐ Y el censo posterior vuelve a preguntarle al catálogo, no al bucle. «El bucle no dio error» no es un censo.


4 · 🪤 Las trampas que costaron una corrida

⛔⛔El primer censo dijo «0 vivas de 131» — cero errores, número absurdo. Preguntaba por el warehouse compartido cuando el inquilino tiene el suyo. El prefijo se resuelve por inquilino; que el número fuera imposible fue lo único que lo delató
El separador de namespace en la URL es %1F (unit separator), no un punto
⚠️Crear un namespace que ya existe da 409, y eso no es un fallo: hace falta que exista, no haberlo creado nosotros

5 · 🏁 DESPLEGADO — y el trinquete demostró para qué sirve

Antes de desplegar, el trinquete cazó lo que ningún test en frío podía: una tabla creada por la puerta justo después de consolidar nació en prod_w_7b500f4d…, el régimen viejo. La cara que acuña el namespace es la desplegada, no la del árbol local — y seguía sirviendo el código anterior. A los diez minutos de existir el trinquete.

⇒ Desplegado desde worktree limpio (3dfdace), y verificado por el RUNTIME:

npx vercel --prod --yes --cwd <worktree limpio>
npx dotenv -e .env.local -- npx tsx scripts/warehouse/s5e-verificar-nacimiento.ts
npm run check:regimen-namespace     # → 110 datasets, régimen «prod», 1 namespace
tabla nueva por la puertanace en prod ✅ (antes: prod_w_<hex>)
E·3 · lecturaVERDE tras mover 110 tablas
trinqueteVERDE · 1 régimen

⚠️ vercel --prod embarca el ÁRBOL DE TRABAJO, no el commit — con ~55 ficheros del owner sin commitear, desplegar desde el directorio principal los habría embarcado. De ahí el worktree. Ver vercel-deploy-desde-worktree.

⭐ Y la regla que esto vuelve a pagar: «desplegado» no es «sirviendo lo desplegado». El Ready de Vercel no lo contesta; lo contesta crear una tabla y mirar dónde nace.


6 · Lo que el trinquete vigila

npm run check:regimen-namespace falla si un dataset materializado tiene un namespace que ① es multinivel, ② lleva el inquilino (w_<hex>), o ③ no es un token de entorno.

⚠️ Un namespace nulo no falla: son datasets que nunca se materializaron en Iceberg. Confundir «no tiene» con «lo tiene mal» obligaría a desactivar el trinquete, y un trinquete desactivado no vigila nada.