MarvelousDB — fix rutas de caché + completar pendientes de imágenes

Fecha: 2026-08-14

Contexto

El panel /coverage (los “pendientes”) de producción (marvelousdb.fly.dev) mostraba 963 personajes sin imagen (96% cobertura). El cron diario corría pero dos cosas lo frenaban.

Diagnóstico (verificado en la máquina de Fly)

  1. Bug de rutas (root cause). Los scripts de mantenimiento (cache-images.js, import-tmdb.js, import-deepl.js, import-comicvine.js, import-wikipedia.js) escribían su estado derivado (img-cache.json, reported-images.json, tmdb-films.json, lore-translations.json, *-progress.json) en path.join(__dirname, ...) = /app/data-scripts/ (capa de imagen, efímera). La API los lee de /app/data/ (el volumen persistente). Resultado: el índice de imágenes nunca se servía y se perdía en cada deploy. Confirmado con Daredevil (id 2027): existía /app/data/img-cache/2027.webp pero la API servía la URL remota de wikia.

    • Los archivos de imagen sí caían en el volumen (public/img/cache → symlink → /app/data/img-cache); solo el JSON de índice estaba mal.
  2. OOM (exit 137). La máquina shared-cpu-1x:256MB (212 MB usable) tiene api.js (~80 MB) + web.js (~74 MB). Los pasos DeepL y SerpAPI del cron morían por SIGKILL al sumar otro proceso Node.

Fix aplicado

  • Scripts: estado derivado ahora en path.dirname(DB_PATH) (= /app/data en prod, data/ en local). cache-images.js además acepta IMG_CACHE_INDEX.
  • import-tmdb.js: ahora honra process.env.DB_PATH (antes no).
  • Dockerfile: seed tolerante (COPY data /app/seed-data/) — ya no falla si faltan data/marvelousdb.sqlite / public/img/cache / img-cache.json.
  • entrypoint.sh: elimina la rama “reemplazar si el seed es más nuevo” (peligrosa: un seed más nuevo pisaría la DB enriquecida por cron). Solo seedea volumen vacío y copia estado derivado con cp -n.

Resultado inmediato (migración + restart)

  • Copié /app/data-scripts/*.json → /app/data/ (403 cachés huérfanos) y reinicié la máquina: 963 → 565 pendientes (los 403 cachés por fin se sirven).
  • Parché los scripts desplegados en /app/data-scripts/ vía fly ssh sftp put (la capa overlay es escribible; sobrevive restarts, se pierde en el próximo deploy — pero el repo ya tiene el fix).

Pendientes restantes (565) y cómo se completan

  • Mythology (294): pasada --commons con búsqueda por nombre desnudo (arte clásico de dominio público). Corriendo en producción. ⚠️ la búsqueda por nombre tiene falsos positivos (nombres que chocan con libros/marcas); los dioses mayores salen bien, los oscuros a veces no.
  • Marvel/Unknown (247) + Modern Gods (10) + misc (~14): NO son fiables en Commons (colisiones de nombres → imágenes equivocadas). Se completan con el cron diario (--browserrun ~50-90/día + SerpAPI 7/día), que ya usa el script corregido.

Notas / deuda

  • El OOM del cron (DeepL/SerpAPI) sigue sin resolver de fondo: subir la máquina a 512 MB o correr los importadores con la web apagada.
  • lore-translations.json estaba perdido en prod (sombrea el volumen); lo re-subí desde el repo.

Actualización (misma sesión, post-commit df3dd85f)

  • El overlay NO sobrevive a fly machine restart: cada restart recrea la máquina con la imagen original y revierte los scripts parcheados vía sftp. Por eso el cron volvía a escribir el índice en /app/data-scripts/. El fix solo queda permanente con fly deploy (ya committeado y seguro: el entrypoint nuevo solo seedea volumen vacío).
  • Retrievals corridos: Browser Run (DuckDuckGo) ~90 imágenes (completó Marvel/Unknown correctamente), Commons (descartado, falsos positivos), SerpAPI (murió por OOM al correr concurrente con browserrun).
  • Números finales honestos: 963 → 567 pendientes (96% → 98%). El índice quedó en ~401 entradas válidas (85 expiradas/corruptas podadas por magic bytes, correcto).
  • La máquina se desestabilizó 2 veces (OOM + proceso matado); se recuperó con fly machine restart --force (el volumen persiste).
  • Pendiente real: fly deploy + subir memoria (512 MB) para que el cron deje de OOM y los scripts corregidos queden horneados en la imagen.

Cierre (deploy + memoria, mismo día)

  • fly scale memory 512 → máquina a 512 MB (MemTotal ~470 MB). OOM resuelto.
  • fly deploy → imagen 227 MB con los scripts corregidos HORNEADOS (verificado: dirname(DB_PATH) en /app/data-scripts/cache-images.js, entrypoint nuevo con seed solo-en-volumen-vacío). El fix ya no se revierte.
  • DB intacta (22,954 chars / 44,514 comics), índice 401 entradas válidas sirviendo (missing 567, 98%).
  • El cron diario ya corre con el script fijo y escribe al volumen; los 567 restantes se rellenan solos (browserrun ~90/día + SerpAPI 7/día).
  • Commons por nombre = calidad variable. Para personajes de cómic, solo browserrun/serpapi (o el paso --fandom del wiki, que ya cubrió PD).