diff --git a/.gitignore b/.gitignore index 59a671a..b874b20 100644 --- a/.gitignore +++ b/.gitignore @@ -36,5 +36,7 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json # DB *.db +*.db-wal +*.db-shm /data/* !data/.gitkeep diff --git a/STATUS.md b/STATUS.md index cb674ed..4cbe2ac 100644 --- a/STATUS.md +++ b/STATUS.md @@ -11,6 +11,7 @@ Estado general: listo para piloto con la junta directiva; 170 tests pasando. Rie - Base de datos y migraciones - Inicialización con PRAGMA FK y timestamps de alta precisión. - Esquema: users, tasks, task_assignments, user_preferences, response_queue (con metadata). + - Modo journal WAL activado (busy_timeout y autocheckpoint configurados) para mejorar concurrencia y rendimiento. - Migrador up-only con tabla schema_migrations; backup automático con VACUUM INTO; baseline si existe esquema previo. - Cola de respuestas - Persistente con workers en background, reintentos con backoff exponencial + jitter, recuperación de items processing tras reinicios, y limpieza/retención. @@ -77,7 +78,7 @@ Estado general: listo para piloto con la junta directiva; 170 tests pasando. Rie - Falta: pruebas E2E reales contra Evolution API (recomendado antes del piloto). ## Notas de despliegue/operación -- Migraciones up-only al arranque; backup con VACUUM INTO previo. +- SQLite en modo WAL; backups consistentes con VACUUM INTO previo; tener en cuenta archivos -wal y -shm. - Persistencia en data/; mapear a volumen y monitorizar tamaño; ejecutar VACUUM periódicamente si procede. - Rotación de logs vía orquestador; considerar niveles/etiquetas para búsquedas. diff --git a/src/db.ts b/src/db.ts index 3902d84..879fd3b 100644 --- a/src/db.ts +++ b/src/db.ts @@ -3,6 +3,18 @@ import { normalizeWhatsAppId } from './utils/whatsapp'; import { mkdirSync } from 'fs'; import { join } from 'path'; +function applyDefaultPragmas(instance: Database): void { + try { + instance.exec(`PRAGMA busy_timeout = 5000;`); + // Intentar activar WAL (si no es soportado, SQLite devolverá 'memory' u otro modo) + instance.query(`PRAGMA journal_mode = WAL`).get(); + instance.exec(`PRAGMA synchronous = NORMAL;`); + instance.exec(`PRAGMA wal_autocheckpoint = 1000;`); + } catch (e) { + console.warn('[db] No se pudieron aplicar PRAGMAs (WAL, busy_timeout...):', e); + } +} + // Function to get a database instance. Defaults to 'data/tasks.db' export function getDb(filename: string = 'tasks.db'): Database { // Try to create data directory if it doesn't exist (ignore if already exists) @@ -11,7 +23,9 @@ export function getDb(filename: string = 'tasks.db'): Database { } catch (err) { if (err.code !== 'EEXIST') throw err; // Only ignore "already exists" errors } - return new Database(join('data', filename)); + const instance = new Database(join('data', filename)); + applyDefaultPragmas(instance); + return instance; } // Default export for the main application database @@ -19,6 +33,9 @@ export const db = getDb(); // Initialize function now accepts a database instance export function initializeDatabase(instance: Database) { + // Aplicar PRAGMAs por defecto (WAL, busy_timeout, etc.) + applyDefaultPragmas(instance); + // Enable foreign key constraints instance.exec(`PRAGMA foreign_keys = ON;`);