浏览代码

Updated plan file

Edited UI in Lovable
gpt-engineer-app[bot] 1 周之前
父节点
当前提交
814804b150
共有 1 个文件被更改,包括 141 次插入0 次删除
  1. 141 0
      .lovable/plan.md

+ 141 - 0
.lovable/plan.md

@@ -0,0 +1,141 @@
+
+
+## Plan : Modifier la purge pour supprimer les articles lus non épinglés
+
+### Contexte actuel
+
+La fonction `purge_old_articles` protège actuellement **tous** les articles ayant une interaction utilisateur (lu OU épinglé). Cela signifie que 7 354 articles sont protégés et quasiment rien n'est jamais supprimé.
+
+### Nouvelle règle demandée
+
+- **Supprimer** : Articles non vus dans les flux depuis 48h+ ET non épinglés
+- **Protéger** : Uniquement les articles épinglés
+
+### Impact estimé
+
+| Métrique | Valeur |
+|----------|--------|
+| Articles actuels | 7 798 |
+| Articles > 48h | 6 463 |
+| Articles qui seraient supprimés | ~6 456 |
+| Articles protégés (épinglés) | 7 |
+| Articles restants après purge | ~1 342 |
+
+### Modification à effectuer
+
+**Migration SQL** - Recréer la fonction `purge_old_articles` :
+
+```sql
+CREATE OR REPLACE FUNCTION public.purge_old_articles()
+RETURNS TABLE(deleted_count integer, admin_emails text[])
+LANGUAGE plpgsql
+SECURITY DEFINER
+SET search_path TO 'public'
+AS $$
+DECLARE
+  v_deleted_count INTEGER;
+  v_admin_emails TEXT[];
+  v_cutoff_date TIMESTAMP WITH TIME ZONE;
+BEGIN
+  -- Calculer la date limite (48 heures)
+  v_cutoff_date := NOW() - INTERVAL '48 hours';
+  
+  -- Récupérer les emails des super users
+  SELECT ARRAY_AGG(email) INTO v_admin_emails
+  FROM public.super_users;
+  
+  -- NOUVELLE LOGIQUE : Supprimer les articles non vus depuis 48h
+  -- SAUF ceux qui sont épinglés par au moins un utilisateur
+  WITH articles_to_delete AS (
+    SELECT a.id
+    FROM public.articles a
+    WHERE a.last_seen_at < v_cutoff_date
+    AND NOT EXISTS (
+      SELECT 1 
+      FROM public.user_articles ua
+      WHERE ua.article_id = a.id
+      AND ua.is_pinned = true  -- Seuls les articles épinglés sont protégés
+    )
+    LIMIT 1000  -- Limiter pour éviter les timeouts
+  ),
+  -- Supprimer d'abord les entrées user_articles associées
+  deleted_user_articles AS (
+    DELETE FROM public.user_articles
+    WHERE article_id IN (SELECT id FROM articles_to_delete)
+    RETURNING article_id
+  ),
+  deleted AS (
+    DELETE FROM public.articles
+    WHERE id IN (SELECT id FROM articles_to_delete)
+    RETURNING id
+  )
+  SELECT COUNT(*)::INTEGER INTO v_deleted_count FROM deleted;
+  
+  -- Log l'opération
+  RAISE NOTICE 'Purge automatique: % articles supprimés (non vus depuis 48h, non épinglés)', v_deleted_count;
+  
+  -- Retourner les résultats
+  RETURN QUERY SELECT v_deleted_count, v_admin_emails;
+END;
+$$;
+```
+
+### Points techniques importants
+
+1. **Cascade des suppressions** : La fonction doit d'abord supprimer les entrées `user_articles` avant de supprimer les articles eux-mêmes (contrainte de clé étrangère)
+
+2. **Limite de 1000** : Conservée pour éviter les timeouts - la purge s'exécutera plusieurs fois si nécessaire
+
+3. **Sécurité** : `SECURITY DEFINER` conservé pour permettre l'accès aux tables protégées par RLS
+
+### Mise à jour de la fonction de test
+
+Également mettre à jour `test_purge_articles` pour refléter la nouvelle logique :
+
+```sql
+CREATE OR REPLACE FUNCTION public.test_purge_articles()
+RETURNS TABLE(articles_to_delete integer, oldest_article_date timestamp with time zone, newest_article_date timestamp with time zone, sample_titles text[])
+LANGUAGE plpgsql
+SECURITY DEFINER
+SET search_path TO 'public'
+AS $$
+DECLARE
+  v_cutoff_date TIMESTAMP WITH TIME ZONE;
+BEGIN
+  v_cutoff_date := NOW() - INTERVAL '48 hours';
+  
+  RETURN QUERY
+  WITH eligible_articles AS (
+    SELECT a.id, a.last_seen_at, a.title
+    FROM public.articles a
+    WHERE a.last_seen_at < v_cutoff_date
+    AND NOT EXISTS (
+      SELECT 1 
+      FROM public.user_articles ua
+      WHERE ua.article_id = a.id
+      AND ua.is_pinned = true  -- Seuls les épinglés sont protégés
+    )
+  ),
+  sample_articles AS (
+    SELECT title
+    FROM eligible_articles
+    ORDER BY last_seen_at DESC
+    LIMIT 5
+  )
+  SELECT 
+    (SELECT COUNT(*)::INTEGER FROM eligible_articles),
+    (SELECT MIN(last_seen_at) FROM eligible_articles),
+    (SELECT MAX(last_seen_at) FROM eligible_articles),
+    (SELECT ARRAY_AGG(title) FROM sample_articles);
+END;
+$$;
+```
+
+### Résumé des changements
+
+| Avant | Après |
+|-------|-------|
+| Articles lus = protégés | Articles lus = supprimés après 48h |
+| Articles épinglés = protégés | Articles épinglés = protégés (inchangé) |
+| ~0 articles supprimés/jour | ~6 400+ articles supprimés |
+