mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-11 17:29:37 +02:00
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)
185 lines
7.4 KiB
JavaScript
185 lines
7.4 KiB
JavaScript
#!/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();
|