Files
quasar/plans/gestor-coleccion-plan-phase-4.md
Benito Rodríguez 4298b003d9 feat: import job runner in-memory
- Añade ImportRunner en memoria con concurrencia configurable
- Tests TDD para enqueue, concurrencia y comportamiento tras stop
- Actualiza /api/import/scan para encolar jobs y registrar errores
- Ajusta tsconfig.json para incluir tests en comprobaciones de tipo
2026-02-08 22:24:56 +01:00

8.9 KiB

Plan: Importador de ROMs (Fase 4)

TL;DR: Estabilizar el entorno de tests y, mediante TDD, implementar la pipeline de importación de ROMs: escaneo de ficheros, cálculo de checksums, verificación contra DATs, persistencia en Prisma y un runner en background. Se comenzará con un runner en memoria y se dejará la puerta abierta para migrar a Redis posteriormente.

Phases

  1. Phase 1: Estabilizar entorno y ejecutar tests

    • Objective: Obtener una línea base reproducible donde yarn --cwd backend test se ejecute y muestre resultados claros.
    • Files/Functions to Modify/Create: backend/tsconfig.json, backend/package.json, backend/prisma/schema.prisma, backend/src/plugins/prisma.ts.
    • Tests to Write: Ninguno nuevo; ejecutar y capturar los tests existentes (backend/tests/**).
    • Steps:
      1. Ejecutar yarn install en la raíz y generar el cliente Prisma (prisma generate) en backend/.
      2. Ejecutar yarn --cwd backend test y documentar fallos.
      3. Corregir problemas de prisma generate o tsconfig y validar que los tests relevantes pasan.
  2. Phase 2: Persistencia básica e integración con la ruta de import

    • Objective: Implementar importService que use scanDirectory y computeHashes para persistir RomFile (upsert por checksum) y, cuando sea posible, vincular/crear Game.
    • Files/Functions to Modify/Create: backend/src/services/importService.ts, actualizar backend/src/routes/import.ts para invocar el servicio.
    • Tests to Write: backend/tests/services/importService.spec.ts, actualizar backend/tests/routes/import.spec.ts para escenarios persist: true/false.
    • Steps:
      1. Escribir tests (falla roja).
      2. Implementar mínimo para pasar tests (green).
      3. Refactor y asegurar idempotencia (re-run tests).
  3. Phase 3: ArchiveReader — soportar zip/7z/chd

    • Objective: Leer/listar contenido de contenedores (ZIP, 7z, CHD) sin extracción completa para indexar ROMs internos.
    • Files/Functions to Modify/Create: backend/src/services/archiveReader.ts; adaptar backend/src/services/fsScanner.ts para delegar en archiveReader cuando isArchive.
    • Tests to Write: backend/tests/services/archiveReader.spec.ts (fixtures: zips/7z/CHD bajo backend/tests/fixtures).
    • Steps:
      1. Añadir tests que describan el comportamiento esperado (falla roja).
      2. Implementar con librería elegida y validar en CI con binarios instalados.
  4. Phase 4: DAT parsing y verificación

    • Objective: Parsear DAT XML y comprobar si un ROM coincide con una entrada DAT (por checksums/size/name).
    • Files/Functions to Modify/Create: backend/src/services/datVerifier.ts (completar), añadir utilidades de parseo XML.
    • Tests to Write: backend/tests/services/datVerifier.spec.ts (unidad + integración, usar INTEGRATION=1 para pruebas que dependan de binarios/fixtures grandes).
    • Steps:
      1. Implementar parseo y matching (falla roja).
      2. Integrarlo en importService para sugerir o asociar Game.
  5. Phase 5: Job runner en memoria (inicio) — migrable a Redis

    • Objective: Implementar un runner en memoria que procese jobs de import con control de concurrencia (IMPORT_CONCURRENCY), estado básico y capacidad de encolar tareas desde la ruta /api/import/scan.
    • Files/Functions to Modify/Create: backend/src/config.ts, backend/src/jobs/importRunner.ts, tests en backend/tests/jobs/importRunner.spec.ts, actualizar backend/src/routes/import.ts para encolar jobs.
    • Tests to Write: backend/tests/jobs/importRunner.spec.ts (enqueue/resolución, concurrencia, getStatus).
    • Steps:
      1. Escribir tests (falla roja).
      2. Implementar runner in-memory (green).
      3. Integrar con la ruta de import y validar comportamiento en tests.
  6. Phase 6: CI e integración de binarios

    • Objective: Preparar workflows para ejecutar pruebas de integración que dependan de binarios (7z, chdman) y asegurar prisma generate en CI.
    • Files/Functions to Modify/Create: .github/workflows/ci.yml, documentación en README.md.
    • Steps:
      1. Crear workflow que haga yarn install, yarn --cwd backend prisma generate, instale binarios (o use contenedor preparado) y ejecute yarn --cwd backend test con INTEGRATION=1 cuando corresponda.

Open Questions

  1. ¿Persistimos ImportJob en DB desde el inicio (útil para resume/retry) o lo dejamos para una futura migración a Redis? (Persistir ahora / Posponer)
  2. ¿En CI preferís instalar 7z/chdman o marcar tests de archive/CHD como opcionales con INTEGRATION=1 y ejecutarlos solo si runner proporciona binarios? (Instalar / Opcional)
  3. ¿Creación automática de Game al no encontrar DAT match? (Crear placeholder con slug / Solo guardar RomFile)
  4. Política de colas a largo plazo: ¿Redis desde el inicio o in-memory ahora y migrar luego? (Usuario eligió: in-memory ahora)

Plan: Importadores y gestión de ROMs (Fase 4)

Implementar servicios para escanear directorios de ROMs, detectar formatos (ZIP/7z/CHD), calcular checksums (CRC32/MD5/SHA1), verificar contra DATs (No-Intro/Redump) y persistir RomFile en la BD. El escaneo se lanzará desde el frontend, correrá como job en background y la ruta a las ROMs será una configuración del sistema (no se envía en cada request). Se añadirá la variable IMPORT_CONCURRENCY con cálculo por defecto.

Phases 4

  1. Phase 4.1: Tests y fixtures (TDD)

    • Objective: Escribir tests y fixtures que guiarán la implementación; los tests deben fallar inicialmente.
    • Files a crear:
      • backend/tests/fixtures/simple-rom.bin — fixture ROM sintética
      • backend/tests/fixtures/nested/nested-rom.bin — fixture en subdirectorio
      • backend/tests/fixtures/dats/sample-no-intro.dat.xml — DAT XML mínimo
      • backend/tests/services/fsScanner.spec.ts
      • backend/tests/services/checksumService.spec.ts
      • backend/tests/services/datVerifier.spec.ts (marcar integración para binarios cuando aplique)
      • backend/tests/routes/import.spec.ts
    • Criterio de aceptación: Los tests existen y fallan por falta de implementación (TDD).
  2. Phase 4.2: Core — Scanner y checksums

    • Objective: Implementar fsScanner y checksumService con streaming y control de concurrencia.
    • Files a crear:
      • backend/src/services/fsScanner.ts
      • backend/src/services/checksumService.ts
      • backend/src/lib/fileTypeDetector.ts
    • Criterio de aceptación: Tests unitarios de Phase 4.1 pasan para los casos no relacionados con archives/CHD.
  3. Phase 4.3: Archives y DAT verification

    • Objective: Implementar archiveReader (ZIP, 7z opcional) y datVerifier.
    • Files a crear:
      • backend/src/services/archiveReader.ts
      • backend/src/services/datVerifier.ts
    • Notas: CHD será soportado opcionalmente mediante chdman (si está instalado en el sistema); en la MVP se tratará CHD como blob para checksums si chdman no está presente.
  4. Phase 4.4: API, job en background y E2E

    • Objective: Añadir endpoint POST /api/import/scan (sin recibir path; usa la ruta preconfigurada), job runner en background, endpoints GET /api/import/status/:taskId y GET /api/import/result/:taskId, y pruebas E2E que verifiquen persistencia en Prisma.
    • Files a crear:
      • backend/src/routes/import.ts
      • backend/src/controllers/importController.ts
      • backend/src/plugins/importJobs.ts (cola en proceso; migrable a Redis/BullMQ)
    • Criterio de aceptación: E2E de import completo pasa en CI (con binarios instalados según sea necesario).

Decisiones tomadas

  • chdman soporte: opcional. Si está instalado, lo usaremos; si no, se calcula checksum y se trata como blob.
  • Endpoint POST /api/import/scan: no recibe path; la ruta a las ROMs se configura en el sistema (env var ROMS_PATH).
  • El job se ejecuta en background; el frontend lanza el job a petición del usuario (botón "Scan").
  • Añadir IMPORT_CONCURRENCY (env var). Valor por defecto: min(8, max(1, os.cpus().length - 1)) si no se configura.
  • Tests que dependen de binarios (7z/chdman): se incluirán como tests de integración y se habilitarán en CI (instalación de binarios en workflow).

Open Questions (resueltas por el usuario):

  1. Soporte chdman opcional — Aprobado.
  2. No enviar path en payload; usar ruta preconfigurada — Aprobado (ROMS_PATH).
  3. Job en background — Aprobado.
  4. IMPORT_CONCURRENCY variable y fórmula por defecto — Aprobado.
  5. Incluir tests dependientes de binarios y instalarlos en CI — Aprobado.

Siguientes pasos (Phase 4.1 - TDD):

  1. Crear fixtures y tests unitarios marcados en Phase 4.1.
  2. Ejecutar yarn --cwd backend test y observar tests fallidos.
  3. Implementar servicios mínimos en Phase 4.2 para pasar tests básicos.

Metadatos:

  • Autor: GitHub Copilot
  • Fecha: 2026-02-08