mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-17 12:18:53 +02:00
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:
8 files changed
+1532
-2
No files matched your search
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Script de migration pour ajouter les champs de tracking pour la purge automatique
|
||||
* - archived_at pour les notes
|
||||
* - completed_at pour global_todos et note_todos
|
||||
*/
|
||||
|
||||
const { Pool } = require('pg');
|
||||
|
||||
const DATABASE_URL = process.env.DATABASE_URL ||
|
||||
`postgresql://${process.env.PGUSER || 'noteflow'}:${process.env.PGPASSWORD || 'noteflow_secure_password_change_me'}@${process.env.PGHOST || 'postgres'}:${process.env.PGPORT || '5499'}/${process.env.PGDATABASE || 'noteflow'}`;
|
||||
|
||||
async function migrate() {
|
||||
const pool = new Pool({ connectionString: DATABASE_URL });
|
||||
|
||||
try {
|
||||
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ MIGRATION: Ajout des champs de tracking pour purge ║');
|
||||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||||
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
|
||||
// 1. Ajouter archived_at à la table notes
|
||||
console.log('📝 Ajout du champ archived_at à la table notes...');
|
||||
await client.query(`
|
||||
ALTER TABLE notes
|
||||
ADD COLUMN IF NOT EXISTS archived_at TIMESTAMP
|
||||
`);
|
||||
console.log('✅ Champ archived_at ajouté\n');
|
||||
|
||||
// 2. Mettre à jour les notes déjà archivées avec updated_at comme date approximative
|
||||
console.log('🔄 Mise à jour des notes archivées existantes...');
|
||||
const archivedNotesUpdate = await client.query(`
|
||||
UPDATE notes
|
||||
SET archived_at = updated_at
|
||||
WHERE archived = TRUE AND archived_at IS NULL
|
||||
`);
|
||||
console.log(`✅ ${archivedNotesUpdate.rowCount} note(s) archivée(s) mise(s) à jour\n`);
|
||||
|
||||
// 3. Ajouter completed_at à la table global_todos
|
||||
console.log('📝 Ajout du champ completed_at à la table global_todos...');
|
||||
await client.query(`
|
||||
ALTER TABLE global_todos
|
||||
ADD COLUMN IF NOT EXISTS completed_at TIMESTAMP
|
||||
`);
|
||||
console.log('✅ Champ completed_at ajouté à global_todos\n');
|
||||
|
||||
// 4. Mettre à jour les global_todos déjà complétées
|
||||
console.log('🔄 Mise à jour des tâches globales complétées existantes...');
|
||||
const globalTodosUpdate = await client.query(`
|
||||
UPDATE global_todos
|
||||
SET completed_at = created_at
|
||||
WHERE completed = TRUE AND completed_at IS NULL
|
||||
`);
|
||||
console.log(`✅ ${globalTodosUpdate.rowCount} tâche(s) globale(s) mise(s) à jour\n`);
|
||||
|
||||
// 5. Ajouter created_at et completed_at à la table note_todos
|
||||
console.log('📝 Ajout des champs created_at et completed_at à la table note_todos...');
|
||||
await client.query(`
|
||||
ALTER TABLE note_todos
|
||||
ADD COLUMN IF NOT EXISTS created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
`);
|
||||
await client.query(`
|
||||
ALTER TABLE note_todos
|
||||
ADD COLUMN IF NOT EXISTS completed_at TIMESTAMP
|
||||
`);
|
||||
console.log('✅ Champs created_at et completed_at ajoutés à note_todos\n');
|
||||
|
||||
// 6. Mettre à jour les note_todos déjà complétées
|
||||
console.log('🔄 Mise à jour des tâches de notes complétées existantes...');
|
||||
const noteTodosUpdate = await client.query(`
|
||||
UPDATE note_todos
|
||||
SET completed_at = CURRENT_TIMESTAMP
|
||||
WHERE completed = TRUE AND completed_at IS NULL
|
||||
`);
|
||||
console.log(`✅ ${noteTodosUpdate.rowCount} tâche(s) de note(s) mise(s) à jour\n`);
|
||||
|
||||
// 7. Créer les triggers pour mettre à jour automatiquement les dates
|
||||
console.log('🔧 Création des triggers pour mise à jour automatique...');
|
||||
|
||||
// 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();
|
||||
`);
|
||||
|
||||
console.log('✅ Triggers créés avec succès\n');
|
||||
|
||||
await client.query('COMMIT');
|
||||
|
||||
console.log('╔════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ ✅ MIGRATION TERMINÉE AVEC SUCCÈS ║');
|
||||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||||
|
||||
console.log('📝 RÉSUMÉ DES CHANGEMENTS:\n');
|
||||
console.log('• Champ archived_at ajouté à la table notes');
|
||||
console.log('• Champ completed_at ajouté aux tables global_todos et note_todos');
|
||||
console.log('• Triggers créés pour mise à jour automatique des dates');
|
||||
console.log('• Données existantes migrées avec succès\n');
|
||||
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
|
||||
await pool.end();
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Erreur:', error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
migrate();
|
||||
Reference in new issue
Block a user