Files
mercadodevida/work/artifacts/F-052/implementer.md
2026-08-19 10:47:17 +02:00

2.1 KiB

Implementer — F-052 (iteración 2)

Cambios (completos)

Código

  • apps/admin/src/app/api/upload/route.ts: tras writeFile, copia a frontend/public/uploads/ y storefront/public/uploads/ con Promise.allSettled. La copia no bloquea el upload principal.
  • project/scripts/monolith.sh: nueva función sync_uploads() que se invoca al final de build_prod() y antes de spawn_service en start_all() para cubrir el caso "arranque en frío sin uploads aún".
  • frontend/src/app/uploads/[filename]/route.ts y storefront/src/app/uploads/[filename]/route.ts: handlers dinámicos (idénticos al del admin) que leen cada petición de public/uploads/<filename> directamente del disco. Imprescindible: Next.js sirve los estáticos de public/ cacheados al build time, por lo que cualquier archivo subido después devolvería 404 sin esta ruta.

Assets

  • frontend/public/uploads/ y storefront/public/uploads/ creados.
  • Archivos sincronizados manualmente para evitar esperar al próximo restart.

Servicios

  • next build re-ejecutado para admin, frontend y storefront.
  • Servicios reiniciados.

Verificación end-to-end

Imágenes existentes (en build)

GET 3004 /uploads/fa7a31db-...jpg → 200 image/jpeg 129711
GET 3003 /uploads/fa7a31db-...jpg → 200 image/jpeg 129711
GET 3005 /uploads/fa7a31db-...jpg → 200 image/jpeg 129711

Imagen subida en caliente (sin rebuild)

POST 3004 /api/upload (admin) → 201 {url: /uploads/a7e3aa30-...jpg}
GET 3004 /uploads/a7e3aa30-...jpg → 200 image/jpeg
GET 3003 /uploads/a7e3aa30-...jpg → 200 image/jpeg
GET 3005 /uploads/a7e3aa30-...jpg → 200 image/jpeg

Favicons siguen 200

GET 3004 /favicon.ico → 200
GET 3005 /favicon.ico → 200

Por qué fue necesaria la 2ª iteración

El mirrorToPeers del admin copia el archivo al disco de frontend/storefront, pero los servicios en producción cachean el listado de public/ al build. Sin una ruta dinámica /uploads/[filename]/, los archivos nuevos solo se sirven si existían al hacer next build. La ruta dinámica los lee frescos del disco en cada request, igual que hace el admin desde F-050.