fix: indexation inversée non-bloquante — run_in_executor
L'étape 'Building inverted index...' au démarrage bloquait l'event loop asyncio, empêchant le serveur de répondre aux requêtes HTTP (navigation, refresh) jusqu'à la fin de l'indexation. - init_inverted_index() exécuté dans ThreadPoolExecutor via run_in_executor - get_inverted_index() ne fait plus de rebuild auto bloquant - Le serveur répond immédiatement, même pendant l'indexation
This commit is contained in:
@@ -172,6 +172,14 @@
|
||||
- [x] **Mise à jour automatique** : quand on clique sur un dossier dans l'arborescence, la page se met à jour
|
||||
- [x] **Déclenchement** : affiché automatiquement quand un vault spécifique est sélectionné
|
||||
|
||||
### ✅ 12. Indexation non-bloquante — FAIT
|
||||
- **Effort** : 0.5 jour | **Impact** : 🟡
|
||||
- L'étape "Building inverted index..." au démarrage bloquait l'event loop asyncio, empêchant le serveur de répondre aux requêtes HTTP (navigation, refresh) jusqu'à la fin de l'indexation.
|
||||
- **Fichiers** : `backend/main.py`, `backend/search.py`
|
||||
- [x] **`init_inverted_index()` dans `run_in_executor`** : exécuté dans le `ThreadPoolExecutor` au lieu de la boucle asyncio principale
|
||||
- [x] **`get_inverted_index()` sans rebuild auto** : ne déclenche plus de rebuild bloquant — retourne l'index vide si pas encore prêt (les recherches retournent 0 résultats jusqu'à la fin de l'indexation)
|
||||
- [x] **Navigation + refresh fonctionnels immédiatement** : le serveur répond aux requêtes HTTP dès le démarrage, même pendant l'indexation
|
||||
|
||||
---
|
||||
|
||||
## 📋 Backlog (P3/P4 — Long terme)
|
||||
|
||||
+5
-2
@@ -573,8 +573,11 @@ async def lifespan(app: FastAPI):
|
||||
logger.info("Background indexing started")
|
||||
await build_index(_progress_cb)
|
||||
|
||||
# Build inverted index for search (one-time, then incremental)
|
||||
init_inverted_index()
|
||||
# Build inverted index in a thread pool to avoid blocking the event loop.
|
||||
# The inverted index rebuild is CPU-bound (tokenization, indexing) and
|
||||
# would freeze HTTP responses if run in the async event loop.
|
||||
loop = asyncio.get_running_loop()
|
||||
await loop.run_in_executor(_search_executor, init_inverted_index)
|
||||
|
||||
# Start file watcher
|
||||
config = _load_config()
|
||||
|
||||
+6
-7
@@ -672,14 +672,13 @@ def init_inverted_index():
|
||||
def get_inverted_index() -> InvertedIndex:
|
||||
"""Return the singleton inverted index.
|
||||
|
||||
Auto-builds on first call if the index has files but the inverted
|
||||
index hasn't been built yet (fallback for paths that don't go through
|
||||
``init_inverted_index()``).
|
||||
The inverted index is built once at startup in a background thread.
|
||||
If called before the build completes, returns an empty index (searches
|
||||
will return no results until the build finishes).
|
||||
|
||||
No automatic rebuild — the startup sequence handles the initial build.
|
||||
Incremental updates are applied via ``update_inverted_index()``.
|
||||
"""
|
||||
if _inverted_index.doc_count == 0 and any(
|
||||
vdata.get("files") for vdata in index.values()
|
||||
):
|
||||
_inverted_index.rebuild()
|
||||
return _inverted_index
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user