|
|
@@ -1,51 +1,28 @@
|
|
|
|
|
|
+## Diagnostique
|
|
|
|
|
|
-## Proteger les articles non lus des abonnements actifs
|
|
|
+### Sources du problème Disk IO
|
|
|
|
|
|
-### Nouvelle regle de purge
|
|
|
+1. **Cron trop fréquent** : `*/10 * * * *` = toutes les 10 min × 49 flux actifs = **~14 000 appels/jour** avec des upserts massifs sur la table `articles`
|
|
|
+2. **Index manquant sur `last_seen_at`** : la purge et les requêtes de filtrage font un full scan sur la table articles (34 MB, 2002 lignes)
|
|
|
+3. **Upsert massif** : chaque fetch-rss fait un upsert de tous les articles du flux, même si rien n'a changé — cela génère des écritures inutiles
|
|
|
|
|
|
-| Statut | Abonnement actif | Action |
|
|
|
-|--------|-------------------|--------|
|
|
|
-| Epingle | Peu importe | Protege |
|
|
|
-| Non lu + Non epingle | Oui (au moins 1 abonne) | Protege |
|
|
|
-| Non lu + Non epingle | Non (aucun abonne) | Supprime |
|
|
|
-| Lu + Non epingle | Peu importe | Supprime |
|
|
|
+### Plan d'action
|
|
|
|
|
|
-### Impact estime (donnees actuelles)
|
|
|
+**1. Réduire la fréquence du cron** (impact immédiat, fort)
|
|
|
+- Passer de `*/10 * * * *` à `*/30 * * * *` (toutes les 30 minutes)
|
|
|
+- Les flux RSS ne se mettent généralement pas à jour plus souvent que ça
|
|
|
+- Réduit les I/O de **3x**
|
|
|
|
|
|
-| Metrique | Valeur |
|
|
|
-|----------|--------|
|
|
|
-| Articles eligibles (> 48h) | 103 |
|
|
|
-| Epingles (proteges) | 9 |
|
|
|
-| Non lus avec abonnement (proteges) | 4 |
|
|
|
-| Non lus sans abonnement (supprimes) | 0 |
|
|
|
-| Lus non epingles (supprimes) | 90 |
|
|
|
-| **Total supprime** | **~90** |
|
|
|
+**2. Ajouter un index sur `last_seen_at`** (impact sur la purge)
|
|
|
+- Migration SQL : `CREATE INDEX idx_articles_last_seen_at ON public.articles USING btree (last_seen_at);`
|
|
|
+- Rend la purge beaucoup plus rapide (index scan au lieu de seq scan)
|
|
|
|
|
|
-### Details techniques
|
|
|
+**3. Optimiser l'upsert dans fetch-rss** (impact moyen)
|
|
|
+- Mettre à jour `last_seen_at` uniquement si l'article existe déjà
|
|
|
+- Ne pas mettre à jour le contenu si le guid existe déjà (éviter les writes inutiles)
|
|
|
|
|
|
-**Migration SQL** - Mise a jour de `purge_old_articles` et `test_purge_articles` :
|
|
|
-
|
|
|
-La condition de protection passe de :
|
|
|
-```text
|
|
|
-NOT EXISTS (is_pinned = true)
|
|
|
-```
|
|
|
-A :
|
|
|
-```text
|
|
|
-NOT EXISTS (is_pinned = true)
|
|
|
-AND NOT (article non lu ET feed a au moins un abonne)
|
|
|
-```
|
|
|
-
|
|
|
-Concretement, un article est supprime si :
|
|
|
-1. `last_seen_at` depasse 48h
|
|
|
-2. Il n'est epingle par personne
|
|
|
-3. ET il est soit lu par au moins un utilisateur, soit son flux n'a aucun abonne actif
|
|
|
-
|
|
|
-La fonction `test_purge_articles` sera aussi mise a jour pour refleter cette logique.
|
|
|
-
|
|
|
-### Fichiers modifies
|
|
|
-
|
|
|
-- **Migration SQL** : nouvelle fonction `purge_old_articles` et `test_purge_articles`
|
|
|
-- **src/data/changelog.ts** : ajout d'une entree pour documenter le changement
|
|
|
-- **.lovable/plan.md** : mise a jour de la documentation
|
|
|
+### Fichiers modifiés
|
|
|
|
|
|
+- **Migration SQL** : ajout de l'index `last_seen_at` + mise à jour du cron à 30 min
|
|
|
+- **`supabase/functions/fetch-rss/index.ts`** : optimiser l'upsert pour ne pas réécrire les articles existants inutilement
|