Files
ObsiGate/docs/features/perf-phase3-86.md
T
bruno f621620593
CI / lint (push) Successful in 1m54s
CI / security (push) Successful in 1m22s
CI / test (push) Successful in 4m23s
CI / build (push) Successful in 1m17s
CI / e2e (push) Successful in 12m9s
feat: optimisation globale des performances #86 (scan differentiel, excalidraw differe, garde-fou replace; inverted index/PDF lazy/caps regex deja livres via BUG-033/040/025)
2026-09-22 19:04:26 -04:00

3.9 KiB

#86 — Optimisation globale des performances (phase 3)

Statut : ✅ livré | Zone : backend (indexer.py, mutations.py) Prérequis déjà livrés : BUG-033 (recherche via inverted index), BUG-040 (PDF lazy), BUG-025 (caps regex).

Contexte

La roadmap #86 demandait : recherche simple + tool IA via l'inverted index, indexation incrémentale + scan différentiel au démarrage, extraction PDF/excalidraw différée et caps CPU sur les opérations regex. Trois de ces cinq points étaient déjà couverts par des correctifs antérieurs ; cette livraison ferme les deux points restants.

Ce qui était déjà livré (rappel)

Point #86 Livré par État
Recherche simple + search_fulltext via inverted index BUG-033 search() récupère ses candidats via l'inverted index (intersection + expansion de préfixes), repli scan pendant la construction
Extraction PDF différée BUG-040 _scan_vault ne lit que les métadonnées ; enrich_pdf_texts() extrait après index
Caps CPU regex BUG-025 validate_regex (longueur ≤ 500, rejet quantificateurs imbriqués), contenu tronqué à 200 kio, matchs plafonnés à 1 000

Livré ici

1. Scan différentiel au démarrage (backend/indexer.py)

  • _scan_vault(..., previous_files) : quand un snapshot {relative_path: file_info} est fourni, toute entrée dont size et modified sont inchangés est réutilisée sans lecture disque ni re-parse (copie du dict, tags recomptés, wikilinks ré-enregistrés depuis le contenu caché pour reconstruire l'index de backlinks).
  • build_index() capture le snapshot précédent avant le clear() et le transmet à chaque scan de vault (via functools.partial pour l'executor) ; reload_single_vault() fait de même pour son vault. Seuls le os.walk + stat (bon marché) tournent à chaque passe ; le retour inclut reused (hits différentiels, loggé par vault).
  • Premier démarrage (aucun snapshot) : comportement identique à avant.

2. Extraction excalidraw différée (backend/indexer.py)

  • Le scan ne lit plus les .excalidraw / .excalidraw.md : titre dérivé du nom de fichier, content vide, flag excalidraw_text_pending (plus de décompression lz-string pendant le scan).
  • enrich_pdf_texts() traite désormais les deux flags (pdf + excalidraw) via _read_excalidraw_indexable_text() exécuté dans l'executor, avec notification du hook d'index incrémental comme pour les PDF. Nom conservé pour compatibilité (tests, main.py, reload_index, reload_single_vault inchangés côté appel).
  • Le chemin incrémental fichier-à-fichier (_index_single_file_sync, watcher) reste immédiat : un seul fichier ne justifie pas le différé.

3. Garde-fou taille sur replace_in_files (backend/services/mutations.py)

  • Nouvelle constante MAX_REPLACE_FILE_BYTES (5 Mio) : tout fichier dépassant le plafond est sauté (warning loggé) au lieu d'être lu intégralement puis balayé par le pattern utilisateur. Complète les caps BUG-025 (qui couvrent la recherche, pas le remplacement qui opère sur le contenu disque complet par nature).

Tests

tests/test_perf_phase3.py (9 tests) : différé excalidraw au scan (.excalidraw + .excalidraw.md), remplissage par l'enrichissement, reused == 0 au premier scan, réutilisation à l'identique, re-parse du fichier modifié, ajout/suppression, skip replace sur fichier surdimensionné + cas passant nominal.

Limites connues

  • Pas de persistance disque de l'index : le différentiel joue sur les rebuilds dans le même processus (reload_index, reload_single_vault), pas entre deux redémarrages (persistance = #85, phase 2).
  • La comparaison size + mtime ne détecte pas une modification qui conserverait taille et mtime à la milliseconde près (cas pathologique, le watcher temps réel couvre les modifications en cours d'exécution).