Ir al contenido

Ruteo core/daily por sufijo

En el modelo de rolling databases, los datos de un local se reparten en varias bases CouchDB: una base core (catálogo y datos estables) y una base daily por día de negocio. El dispositivo no conoce ni envía el nombre físico de ninguna de esas bases: solo envía un sufijo lógico (core o daily_<YYYYMMDD>), y el proxy de tables-socket compone el nombre físico completo a partir del token.

El nombre físico de una base depende de tres datos que el dispositivo no debe fijar por su cuenta:

  • el dbPrefix (entorno de deploy: testing / staging / prod),
  • el companyId,
  • el restaurantId.

companyId y restaurantId viven en el token JWT (resueltos por el auth.middleware de tables-socket, no por el cliente), y el dbPrefix es configuración del servidor. Si el dispositivo enviara el nombre físico completo, el proxy lo duplicaría o, peor, lo mis-rutearía al empezar con _ (prefijo vacío). Manteniendo el nombre físico en un solo lugar —el proxy— el cliente y el servidor hablan siempre el mismo sufijo lógico.

El parser y el constructor de nombres viven en un archivo de contrato idéntico en ambos repos (tables-sdk/src/contracts/day-db-naming.ts y tables-socket/src/contracts/day-db-naming.ts). Que el dispositivo y el servidor parseen idéntico es crítico: un parser que difiera mis-rutea o dropea la base equivocada.

El formato físico es:

core: <dbPrefix>_<companyId>_<restaurantId>_core
daily: <dbPrefix>_<companyId>_<restaurantId>_daily_<YYYYMMDD>

Donde dbPrefix es el entorno (testing / staging / prod). Hay una sola base daily por día (agrupa todos los tipos de documentos dinámicos), sin epoch: la base de un día se crea una vez (idempotente).

Toda lectura/escritura del cliente contra CouchDB pasa por el proxy de tables-socket en /couchdb/* (autenticación HMAC; el cliente nunca accede a CouchDB directo). El proxy toma el sufijo lógico de la ruta y lo expande:

tables-socket/src/proxy/couchdb-proxy.service.ts
buildTargetPath(originalPath, companyId, restaurantId) {
let path = originalPath.replace(/^\/couchdb\/?/, '').replace(/^\//, '');
// path === 'core' | 'daily_20260622' | '_changes' | ...
return `/${this.dbPrefix}_${companyId}_${restaurantId}_${path}`;
}
  1. El dispositivo arma una petición CouchDB cuyo segmento de base es el sufijo lógico (core o daily_<YYYYMMDD>).

  2. El proxy resuelve companyId y restaurantId desde el token (AuthInfo), no desde la ruta.

  3. El proxy antepone el dbPrefix de su configuración y compone el nombre físico completo, reenviando la petición a CouchDB con los headers HMAC.

En el SDK, Database decide el sufijo de la base core según el flag rollingDb del tenant:

  • con rollingDb activo, el sufijo efectivo es core;
  • sin él (modo legacy / CORE-only), sigue siendo tables-prod.

El SDK construye la URL remota reemplazando solo el último segmento de la ruta por el sufijo lógico (_coreRemoteUrl.../core), nunca por el nombre físico. El cambio toma efecto al (re)inicializar el dispositivo; cambiar el flag en vivo requiere re-bootstrap (re-login o reinicio).

El manifest expone el sufijo, no el nombre físico

Sección titulada «El manifest expone el sufijo, no el nombre físico»

¿Y de dónde saca el dispositivo el sufijo daily_<YYYYMMDD> correcto del día? Del documento singleton day_manifest, que el servidor escribe en la base core (derivado de la tabla SQL day_databases) y el dispositivo lee. Es la fuente server-authoritative y offline-capable de qué base daily está activa y cuáles montar como overlay; reemplaza al reloj del dispositivo para decidir el día de negocio. La dirección es única: SQL → core; el dispositivo nunca lo escribe.

Coherente con todo lo anterior, el manifest expone sufijos lógicos, no nombres físicos:

// tables-socket — buildCoreManifest (day-db-lifecycle.service.ts)
const overlays = rows
.filter((r) => r.state === 'DRAINING')
.map((r) => ({ businessDay: r.businessDay, dbName: `daily_${r.businessDay}` }));

Así, dispositivo y proxy hablan el mismo sufijo (daily_<YYYYMMDD>) y el nombre físico vive en un solo lugar. La columna day_databases.dbName en SQL sí guarda el nombre físico completo, pero solo para las operaciones server-side.

  • El dispositivo envía solo el sufijo lógico: core o daily_<YYYYMMDD>.
  • El proxy compone el nombre físico <dbPrefix>_<companyId>_<restaurantId>_<sufijo> tomando companyId y restaurantId del token y dbPrefix de su configuración.
  • El day_manifest (en core, escrito por el servidor) le dice al dispositivo qué sufijo daily usar; también expone sufijos lógicos, no nombres físicos.
  • El contrato day-db-naming.ts es idéntico en SDK y tables-socket para que ambos parseen igual.

Más sobre el ciclo de vida de las bases y la rotación diaria en rolling databases; sobre el proxy de CouchDB, JWT y HMAC en infraestructura.