Feat: Ajout du système de purge automatique de la base de données

Implémente un système complet de purge automatique pour maintenir
la base de données propre et performante.

Fonctionnalités ajoutées :
- Migration pour ajouter les champs de tracking (archived_at, completed_at)
- Triggers PostgreSQL pour mise à jour automatique des dates
- Script de purge manuel avec mode simulation (dry-run)
- Scheduler automatique configurable (défaut: 24h)
- Routes API admin pour contrôle et monitoring
- Documentation complète

Éléments purgés :
- Flux RSS désactivés (tous)
- Tâches complétées > 3 mois (configurable)
- Notes archivées > 6 mois (configurable)
- Rendez-vous passés > 6 mois (configurable)

Scripts npm ajoutés :
- npm run db:migrate - Exécuter la migration
- npm run db:cleanup - Purge manuelle
- npm run db:cleanup:dry-run - Simulation de purge

Routes API ajoutées :
- POST /api/admin/cleanup - Déclencher la purge
- GET /api/admin/cleanup/preview - Prévisualiser la purge
- GET /api/admin/cleanup/status - Statut du scheduler
- GET /api/admin/stats - Statistiques DB

Configuration via variables d'environnement :
- CLEANUP_ENABLED (défaut: true)
- CLEANUP_INTERVAL_HOURS (défaut: 24)
- CLEANUP_COMPLETED_TASKS_DAYS (défaut: 90)
- CLEANUP_ARCHIVED_NOTES_DAYS (défaut: 180)
- CLEANUP_PAST_EVENTS_DAYS (défaut: 180)
This commit is contained in:
Claude committed 2025-11-19 06:49:27 +00:00
1 parent 0359ebe22a
commit 86e825b9d1
8 files changed
+1532 -2

No files matched your search

+77 -1
View File
@@ -59,6 +59,7 @@ async function initDatabase() {
content TEXT,
image_filename TEXT,
archived BOOLEAN DEFAULT FALSE,
archived_at TIMESTAMP,
priority INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
@@ -72,7 +73,9 @@ async function initDatabase() {
note_id INTEGER NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
text TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE,
position INTEGER DEFAULT 0
completed_at TIMESTAMP,
position INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
@@ -83,6 +86,7 @@ async function initDatabase() {
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
text TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE,
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
@@ -221,6 +225,78 @@ async function initDatabase() {
logger.info('✓ Tables PostgreSQL créées avec succès');
// Créer les triggers pour mise à jour automatique des dates de purge
// Trigger pour notes.archived_at
await client.query(`
CREATE OR REPLACE FUNCTION update_notes_archived_at()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.archived = TRUE AND OLD.archived = FALSE THEN
NEW.archived_at = CURRENT_TIMESTAMP;
ELSIF NEW.archived = FALSE THEN
NEW.archived_at = NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
`);
await client.query(`
DROP TRIGGER IF EXISTS trigger_notes_archived_at ON notes;
CREATE TRIGGER trigger_notes_archived_at
BEFORE UPDATE ON notes
FOR EACH ROW
EXECUTE FUNCTION update_notes_archived_at();
`);
// Trigger pour global_todos.completed_at
await client.query(`
CREATE OR REPLACE FUNCTION update_global_todos_completed_at()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.completed = TRUE AND OLD.completed = FALSE THEN
NEW.completed_at = CURRENT_TIMESTAMP;
ELSIF NEW.completed = FALSE THEN
NEW.completed_at = NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
`);
await client.query(`
DROP TRIGGER IF EXISTS trigger_global_todos_completed_at ON global_todos;
CREATE TRIGGER trigger_global_todos_completed_at
BEFORE UPDATE ON global_todos
FOR EACH ROW
EXECUTE FUNCTION update_global_todos_completed_at();
`);
// Trigger pour note_todos.completed_at
await client.query(`
CREATE OR REPLACE FUNCTION update_note_todos_completed_at()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.completed = TRUE AND (OLD.completed IS NULL OR OLD.completed = FALSE) THEN
NEW.completed_at = CURRENT_TIMESTAMP;
ELSIF NEW.completed = FALSE THEN
NEW.completed_at = NULL;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
`);
await client.query(`
DROP TRIGGER IF EXISTS trigger_note_todos_completed_at ON note_todos;
CREATE TRIGGER trigger_note_todos_completed_at
BEFORE UPDATE ON note_todos
FOR EACH ROW
EXECUTE FUNCTION update_note_todos_completed_at();
`);
logger.info('✓ Triggers de purge automatique créés');
// Créer l'utilisateur admin par défaut si la table est vide
const usersCount = await client.query('SELECT COUNT(*) as count FROM users');