ecosystem-wikicómo extender los templates sin romper sus convenciones
‹ todo el contenido

Lo que está duplicado a propósito

notification-stack
último cambio 2026-09-25

Hay dos ficheros que existen por duplicado en notification-api y notification-worker, y no es un descuido. Si vas a tocar alguno, esta es la página.

src/core/queue-contract.ts

Es el formato de lo que viaja por Redis: los nombres de las colas y las interfaces EmailData y PushData. Hoy es byte a byte idéntico en los dos repos, y su propia cabecera dice quién manda:

notification-api es la fuente de la verdad — este fichero debe permanecer idéntico en notification-worker, empujado allí con pnpm queue-contract:push-to-worker.

Ese script es literalmente un cp:

cp src/core/queue-contract.ts ../notification-worker/src/core/queue-contract.ts

Y se vuelve a copiar en cada build de Docker, el mismo mecanismo que usa prisma/schema.prisma.

Qué pasa si divergen: el CI del worker lo detecta. Antes de desplegar hace diff de los dos ficheros contra main de notification-api y falla si no son idénticos. Sin ese paso no se vería nada al compilar: los dos repos siguen compilando por separado, porque cada uno tiene su copia y su copia es coherente consigo misma. Lo que falla es en ejecución, con trabajos ya encolados: el productor mete un campo que el consumidor no lee, o el consumidor espera uno que nunca llega. No hay tipo que te proteja de esto: te protege el diff del CI.

prisma/schema.prisma

Misma historia y misma dirección: manda notification-api, se empuja al worker. Los dos servicios hablan con la misma base de datos, así que dos schemas distintos significa dos clientes Prisma que discrepan sobre las mismas tablas.

Ojo con una asimetría: core/constants.ts no es parte de lo sincronizado. Se parece mucho entre repos pero difiere a propósito —las rutas de import de los enums de Prisma no coinciden, y el worker no reexporta JOBS porque no lo usa—. No lo copies de un lado al otro.

Por qué no es un paquete compartido

Es lo primero que apetece hacer, y sería peor. Un paquete npm compartido entre dos repos que se despliegan por separado te obliga a publicar y versionar para cambiar un campo, y a resolver en qué orden despliegas. Con el cp pagas una copia manual; con el paquete pagas una release entera cada vez.

Es un tradeoff deliberado, no deuda pendiente.

Cómo cambiar el contrato sin romper producción

El orden importa, y el motivo es que hay trabajos en vuelo:

  1. Cambia queue-contract.ts en notification-api.
  2. Empújalo al worker y ajusta el consumidor.
  3. Publica primero la api. El CI del worker compara sus copias con main de la api, así que si el worker va antes su CI falla y no despliega. El deploy de la api reconstruye además el worker con el main que tenga en ese momento.
  4. Después el worker, con el consumidor ya ajustado.

Entre los pasos 3 y 4 la api nueva convive con el consumidor anterior, así que el cambio tiene que ser compatible hacia atrás: un campo nuevo que el worker aún no lee no rompe nada. Si no lo es, los trabajos en cola con el formato nuevo fallan sus tres intentos.

Si el cambio es incompatible en los dos sentidos —renombrar un campo, no añadirlo— haz dos pasos: añade el nuevo, despliega ambos, y quita el viejo en un despliegue posterior, cuando ya no queden trabajos antiguos en la cola. Es la misma cautela que documenta el RENAME COLUMN pendiente de providerId.